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

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

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

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

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

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

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

  1. #include<cstdio>
  2. #include<algorithm>
  3. #include<cstring>
  4. typedef long long ll;
  5. using namespace std;
  6. int T,n,K,a[3005];
  7. bool notprime[2000005];
  8. bool cmp(const int &a,const int &b){
  9. return a>b;
  10. }
  11. int e,first[3005],next[3005*3005],v[3005*3005];
  12. void AddEdge(int U,int V){
  13. v[++e]=V;
  14. next[e]=first[U];
  15. first[U]=e;
  16. }
  17. int mat[3005],yi;
  18. bool vis[3005];
  19. bool dfs(int U)
  20. {
  21. for(int i=first[U];i;i=next[i]){
  22. if(!vis[v[i]]){
  23. vis[v[i]]=1;
  24. if(mat[v[i]]==-1 || dfs(mat[v[i]])){
  25. mat[v[i]]=U;
  26. return 1;
  27. }
  28. }
  29. }
  30. return 0;
  31. }
  32. int ru[3005],ru1[3005],right1,right2;
  33. int main(){
  34. notprime[1]=1;
  35. for(int i=2;i<=2000000;++i){
  36. for(ll j=(ll)i*(ll)i;j<=2000000ll;j+=(ll)i){
  37. notprime[j]=1;
  38. }
  39. }
  40. scanf("%d",&T);
  41. for(;T;--T){
  42. e=0;
  43. memset(mat,-1,sizeof(mat));
  44. memset(first,0,sizeof(first));
  45. memset(ru,0,sizeof(ru));
  46. memset(ru1,0,sizeof(ru1));
  47. scanf("%d%d",&n,&K);
  48. yi=0;
  49. for(int i=1;i<=n;++i){
  50. scanf("%d",&a[i]);
  51. if(a[i]==1){
  52. ++yi;
  53. }
  54. }
  55. sort(a+1,a+n+1,cmp);
  56. for(int i=1;i<=n;++i){
  57. for(int j=i+1;j<=n;++j){
  58. if(!(a[i]==1 && a[j]==1) && !notprime[a[i]+a[j]]){
  59. if(a[i]&1){
  60. AddEdge(i,j);
  61. ++ru[j];
  62. if(a[i]==1){
  63. ++ru1[j];
  64. }
  65. }
  66. else{
  67. AddEdge(j,i);
  68. ++ru[i];
  69. if(a[j]==1){
  70. ++ru1[i];
  71. }
  72. }
  73. }
  74. }
  75. }
  76. bool tp=(yi==1 ? 1 : 0);
  77. right1=right2=0;
  78. for(int i=1;i<=n;++i){
  79. if(!(a[i]&1)){
  80. if(ru[i]>ru1[i]){
  81. ++right1;
  82. }
  83. if(ru[i]){
  84. ++right2;
  85. }
  86. if(ru1[i]){
  87. tp=0;
  88. }
  89. }
  90. }
  91. if(tp){
  92. yi=0;
  93. }
  94. int sum=0,cnt=0,nowleft=0,ans=0;
  95. for(int i=1;i<=n;++i){
  96. if((a[i]&1)){
  97. ++nowleft;
  98. if(a[i]!=1 && first[i]){
  99. memset(vis,0,sizeof(vis));
  100. if(dfs(i)){
  101. ++sum;
  102. }
  103. }
  104. else if(a[i]==1 && !tp){
  105. if(!cnt){
  106. if(K<=sum+yi/2){
  107. ans=max(ans,2*K);
  108. }
  109. else{
  110. ans=max(ans,2*sum+yi+min(K-sum-yi/2-yi%2,nowleft-1+right1-sum*2));
  111. }
  112. }
  113. ++cnt;
  114. memset(vis,0,sizeof(vis));
  115. if(dfs(i)){
  116. ++sum;
  117. }
  118. if(K<=sum+(yi-cnt)/2){
  119. ans=max(ans,2*K);
  120. }
  121. else{
  122. ans=max(ans,2*sum+(yi-cnt)+min(K-sum-(yi-cnt)/2-(yi-cnt)%2,nowleft+right2-sum*2));
  123. }
  124. }
  125. }
  126. }
  127. if(!cnt){
  128. if(K<=sum){
  129. ans=max(ans,2*K);
  130. }
  131. else{
  132. ans=max(ans,2*sum+min(K-sum,nowleft+right1-sum*2));
  133. }
  134. }
  135. printf("%d\n",ans);
  136. }
  137. return 0;
  138. }

【二分图最大匹配】【匈牙利算法】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. 用体渲染的方法在Unity中渲染云(18/4/4更新)

    github: https://github.com/yangrc1234/VolumeCloud 更新的内容在底部 最近在知乎上看到一篇文章讲云层的渲染(https://zhuanlan.zhihu ...

  2. Django初探(模板渲染、模板语音、simple_tag、母版子版、静态配置文件)

    一.首先我们用PyCharm来创建一个Django项目 终端命令:django-admin startproject sitename 图形创建:   这样一个Django项目就创建完成了,上面可以看 ...

  3. Django之组合搜索组件(一)

    什么是组合搜索呢? 比如你想买车,但手里只有10万块!所以你只能在10万块的车里挑选,但你喜欢黑色,因为觉得很高端大气上档次,说白了就是装逼杠杠的!之后售车姐给你拿了个表表,你看到了低于10万块且颜色 ...

  4. javascript 中的 this 关键字详解

    1.javascript 中 什么是 this? this 指的是当前行为执行的主体,或者是当前方法执行的主体 context:是当前行为或者方法执行的环境 实例: xx 去北京饭店吃东西:上下文是“ ...

  5. VC拷贝字符串到剪切板

    ] ="中华人民共和国"; DWORD dwLength = ; // 要复制的字串长度 HANDLE hGlobalMemory = GlobalAlloc(GHND, dwLe ...

  6. android 系统的休眠与唤醒+linux 系统休眠

    Android休眠与唤醒驱动流程分析 标准Linux休眠过程: powermanagement notifiers are executed with PM_SUSPEND_PREPARE tasks ...

  7. caffe Python API 之图片预处理

    # 设定图片的shape格式为网络data层格式 transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape}) ...

  8. BeanUtils封装对象时一直提示ClassNotFoundException:org.apache.commons.beanutils.BeanUtils

    导包明明正确了,依赖包也全都导对了,还是出错. 困扰了3天. 后来看到这篇博文,https://blog.csdn.net/yanshaoshuai/article/details/81624890 ...

  9. golang基础之二-基本数据类型和操作符

    文件名&关键字&标识符 所有go源码都是以.go结尾 标识符以字母或下划线开头,大小写敏感 下划线_是特殊标识符,用户忽略结果 保留关键字 导入包时可以设置别名 下面是保留关键字: b ...

  10. python基础(11)--面向对象

    1.概述 面向过程:根据业务的逻辑从上到下写代码 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可 面向对象:对函数进行分类和封装,让开发更快更好更强 面向过程编程最易被初学者接受 ...