题意:给你n个正整数,一对和为素数的数为一个合法数对。你选不超过K个合法数对,使得你选的数对涉及到的数的数量最大化。输出这个值。

所有1之间是可以任意两两配对的。

把奇数放在左侧,偶数放在右侧。

考虑当前要使用多少个“1”,动态更新最大匹配。

如果K不超过 最大匹配数 + 剩下的还没使用过的1数/2 ,那么直接输出这个和*2即可。

否则剩下的用剩余的1(最多一个)+没被匹配上的但是不孤立(有边)的点数 补齐,这样不断更新答案。

有一个坑点是如果1恰好只有一个的话,而且没有能和它加起来组成素数的数的话,就要忽略掉这个1。

#include<cstdio>
#include<algorithm>
#include<cstring>
typedef long long ll;
using namespace std;
int T,n,K,a[3005];
bool notprime[2000005];
bool cmp(const int &a,const int &b){
return a>b;
}
int e,first[3005],next[3005*3005],v[3005*3005];
void AddEdge(int U,int V){
v[++e]=V;
next[e]=first[U];
first[U]=e;
}
int mat[3005],yi;
bool vis[3005];
bool dfs(int U)
{
for(int i=first[U];i;i=next[i]){
if(!vis[v[i]]){
vis[v[i]]=1;
if(mat[v[i]]==-1 || dfs(mat[v[i]])){
mat[v[i]]=U;
return 1;
}
}
}
return 0;
}
int ru[3005],ru1[3005],right1,right2;
int main(){
notprime[1]=1;
for(int i=2;i<=2000000;++i){
for(ll j=(ll)i*(ll)i;j<=2000000ll;j+=(ll)i){
notprime[j]=1;
}
}
scanf("%d",&T);
for(;T;--T){
e=0;
memset(mat,-1,sizeof(mat));
memset(first,0,sizeof(first));
memset(ru,0,sizeof(ru));
memset(ru1,0,sizeof(ru1));
scanf("%d%d",&n,&K);
yi=0;
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(a[i]==1){
++yi;
}
}
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
if(!(a[i]==1 && a[j]==1) && !notprime[a[i]+a[j]]){
if(a[i]&1){
AddEdge(i,j);
++ru[j];
if(a[i]==1){
++ru1[j];
}
}
else{
AddEdge(j,i);
++ru[i];
if(a[j]==1){
++ru1[i];
}
}
}
}
}
bool tp=(yi==1 ? 1 : 0);
right1=right2=0;
for(int i=1;i<=n;++i){
if(!(a[i]&1)){
if(ru[i]>ru1[i]){
++right1;
}
if(ru[i]){
++right2;
}
if(ru1[i]){
tp=0;
}
}
}
if(tp){
yi=0;
}
int sum=0,cnt=0,nowleft=0,ans=0;
for(int i=1;i<=n;++i){
if((a[i]&1)){
++nowleft;
if(a[i]!=1 && first[i]){
memset(vis,0,sizeof(vis));
if(dfs(i)){
++sum;
}
}
else if(a[i]==1 && !tp){
if(!cnt){
if(K<=sum+yi/2){
ans=max(ans,2*K);
}
else{
ans=max(ans,2*sum+yi+min(K-sum-yi/2-yi%2,nowleft-1+right1-sum*2));
}
}
++cnt;
memset(vis,0,sizeof(vis));
if(dfs(i)){
++sum;
}
if(K<=sum+(yi-cnt)/2){
ans=max(ans,2*K);
}
else{
ans=max(ans,2*sum+(yi-cnt)+min(K-sum-(yi-cnt)/2-(yi-cnt)%2,nowleft+right2-sum*2));
}
}
}
}
if(!cnt){
if(K<=sum){
ans=max(ans,2*K);
}
else{
ans=max(ans,2*sum+min(K-sum,nowleft+right1-sum*2));
}
}
printf("%d\n",ans);
}
return 0;
}

【二分图最大匹配】【匈牙利算法】zoj3988 Prime Set的更多相关文章

  1. UESTC 919 SOUND OF DESTINY --二分图最大匹配+匈牙利算法

    二分图最大匹配的匈牙利算法模板题. 由题目易知,需求二分图的最大匹配数,采取匈牙利算法,并采用邻接表来存储边,用邻接矩阵会超时,因为邻接表复杂度O(nm),而邻接矩阵最坏情况下复杂度可达O(n^3). ...

  2. Ural1109_Conference(二分图最大匹配/匈牙利算法/网络最大流)

    解题报告 二分图第一题. 题目描写叙述: 为了參加即将召开的会议,A国派出M位代表,B国派出N位代表,(N,M<=1000) 会议召开前,选出K队代表,每对代表必须一个是A国的,一个是B国的; ...

  3. HDU 1045 - Fire Net - [DFS][二分图最大匹配][匈牙利算法模板][最大流求二分图最大匹配]

    题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=1045 Time Limit: 2000/1000 MS (Java/Others) Mem ...

  4. HDU1068 (二分图最大匹配匈牙利算法)

    Girls and Boys Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  5. poj - 3041 Asteroids (二分图最大匹配+匈牙利算法)

    http://poj.org/problem?id=3041 在n*n的网格中有K颗小行星,小行星i的位置是(Ri,Ci),现在有一个强有力的武器能够用一发光速将一整行或一整列的小行星轰为灰烬,想要利 ...

  6. 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids

    题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...

  7. HDU - 1045 Fire Net (二分图最大匹配-匈牙利算法)

    (点击此处查看原题) 匈牙利算法简介 个人认为这个算法是一种贪心+暴力的算法,对于二分图的两部X和Y,记x为X部一点,y为Y部一点,我们枚举X的每个点x,如果Y部存在匹配的点y并且y没有被其他的x匹配 ...

  8. 51Nod 2006 飞行员配对(二分图最大匹配)-匈牙利算法

    2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 第二次世界大战时期,英国皇家空军从沦陷国 ...

  9. poj 3894 System Engineer (二分图最大匹配--匈牙利算法)

    System Engineer Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 507   Accepted: 217 Des ...

  10. POJ1274:The Perfect Stall(二分图最大匹配 匈牙利算法)

    The Perfect Stall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 17895   Accepted: 814 ...

随机推荐

  1. 认识单点登录cas

    么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分 1.登录 相比于单 ...

  2. kali2.0安装虚拟机工具

    kali2.0无法安装虚拟机工具,显示VMware Tools无法用于该虚拟机,或者安装之后无法进行复制.粘贴等操作. 解决办法: step1: 更换源 root@starnight:~# vim / ...

  3. LintCode题解之子树

    思路: 最简单的方法,依次遍历比较就可以了. AC代码: /** * Definition of TreeNode: * public class TreeNode { * public int va ...

  4. 21、利用selenium进行Web测试

    一.案例实施步骤思路分析 1.寻包 2.指定浏览器(实例化浏览器对象) 3.打开项目 4.找到元素(定位元素) 5.操作元素 6.暂停 7.关闭二.元素定位[重点] 1.id 说明:通过元素的id属性 ...

  5. linux下C语言实现多线程通信—环形缓冲区,可用于生产者(producer)/消费者(consumer)【转】

    转自:http://blog.chinaunix.net/uid-28458801-id-4262445.html 操作系统:ubuntu10.04 前言:     在嵌入式开发中,只要是带操作系统的 ...

  6. 有关mysql的innodb_flush_log_at_trx_commit参数【转】

    一.参数解释 0:log buffer将每秒一次地写入log file中,并且log file的flush(刷到磁盘)操作同时进行.该模式下在事务提交的时候,不会主动触发写入磁盘的操作. 1:每次事务 ...

  7. 【Learn】CSS定义

    CSS基础语法 本文用于介绍CSS相关的知识,用于记录自己的学习笔记.由于我已经熟悉了部分的HTML,所以相关的概念也不在这里进行描述了,直接写自己的一些心得感悟. 1.CSS规则 CSS是由两个主要 ...

  8. Linux时间结构体和获得时间函数

    关于Linux下时间编程的问题: 1. Linux下与时间有关的结构体 struct timeval { int tv_sec; int tv_usec; }; 其中tv_sec是由凌晨开始算起的秒数 ...

  9. 【hdoj_2100】Lovekey(大数+字符处理)

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=2100 根据题目意思,现将字符串转化为10进制,再采用10进制加法相加,再转化为26进制. 另一种直接的思路 ...

  10. [loj6039]「雅礼集训 2017 Day5」珠宝 dp+决策单调性+分治

    https://loj.ac/problem/6039 我们设dp[i][j]表示考虑所有价值小于等于i的物品,带了j块钱的最大吸引力. 对于ci相同的物品,我们一定是从大到小选k个物品,又发现最大的 ...