题意:给你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. 39、请用代码简答实现stack

    栈和队列是两种基本的数据结构,同为容器类型.两者根本的区别在于: stack:后进先出 queue:先进先出 PS:stack和queue是不能通过查询具体某一个位置的元素而进行操作的.但是他们的排列 ...

  2. 蓝色的cms网站后台管理模板——后台

    链接:http://pan.baidu.com/s/1c138cwC 密码:9vy9

  3. Spring提供的iBatis的SqlMap配置

    1.    applicationContext.xml <!-- Spring提供的iBatis的SqlMap配置--> <bean id="sqlMapClient&q ...

  4. python并发编程之gevent协程(四)

    协程的含义就不再提,在py2和py3的早期版本中,python协程的主流实现方法是使用gevent模块.由于协程对于操作系统是无感知的,所以其切换需要程序员自己去完成. 系列文章 python并发编程 ...

  5. python设计模式之常用创建模式总结(二)

    前言 设计模式的创建模式终极目标是如何使用最少量最少需要修改的代码,传递最少的参数,消耗系统最少的资源创建可用的类的实例对象. 系列文章 python设计模式之单例模式(一) python设计模式之常 ...

  6. CentOS 6.6下目录结构及其主要作用

    今天我们总结一下CentOS 6.6的linux的目录结构,一个系统的目录众多,这里我们主要认识一下,根目录下的主要目录,首先我们可以通过tree命令查看一次根目录下一层目录都有什么目录, 补充:不能 ...

  7. 集合框架之Map学习

    Map接口的实现类有HashTable.HashMap.TreeMap等,文章学习整理了“ Map和HashMap的使用方法”. /** * Map和HashMap的使用方法 */public sta ...

  8. Python编程规范精简版

    用四个空格缩进,不要用tab键:四个空格是在较小缩进(可以允许更大的嵌套深度)和较大缩进(可读性更好)之间的一个很好的折中.制表符会带来混乱,最好不要使用: 包装行保证每行不超过79个字符:这对那些使 ...

  9. rcnn ->fast rcnn->faster rcnn物体检测论文

    faster rcnn中的rpn网络: 特征可以看做一个尺度51*39的256通道图像,对于该图像的每一个位置,考虑9个可能的候选窗口:三种面积{1282,2562,5122}×三种比例{1:1,1: ...

  10. 使用Opencv时编译错误

    1)无法打开包括文件: “cv.h”: No such file or directory 我的配置文件没有问题,但是一直报错,我是在HEVC测试软件HM中调用了opencv. HM有很多个工程,我只 ...