ZOJ 3988 && 2017CCPC秦皇岛 H:Prime Set(二分匹配)
来源:互联网 发布:网络玻璃的意思是什么 编辑:程序博客网 时间:2024/05/16 15:20
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3988
题意:
给你n个数,如果{i, j}满足i!=j && a[i]+a[j]是一个质数,那么称{i, j}是个Pset
之后再给你一个k,然你找出最多k个这样的Pset二元组,使得所有二元组中出现的元素尽可能多
例如样例:
5 3
3 4 12 3 6
满足条件的二元组只有(1, 2)和(2, 4),所以这两个都选上就好了,答案为3
思路:
暴力所有二元组{i, j}
如果{i, j}是个Pset,并且a[i]!=1 || a[j]!=1,那么i到j连一条无向边
这个时候得出的图很显然是二分图
为什么呢?因为质数一定是个奇数(除了2,不过a[i]!=1 || a[j]!=1所以不会出现2这种情况),而奇数=奇数+偶数
这样的话每条边的两端一定是个奇数和一个偶数,把所有奇数的点放在左边,偶数放在右边,得证
……
到这里问题就好办了,贪心就好了
求出二分图的最大匹配,最大匹配中的每个Pset都会对答案贡献2,除此之外剩下所有没有用的1,两两配对对答案贡献也是2(不过注意一个细节:例如样例1 1 4 13,如果1和4匹配上了就错了!所以二分匹配时一定要让1最后匹配),贡献为2的Pset处理完了,剩下的贡献一定只能为1了,加上就是答案
#include<stdio.h> #include<string.h> #include<vector> #include<algorithm> using namespace std; #define LL long long vector<int> G[3005]; int n, a[3005], vis[3005], val[3005], link[3005], flag[2000005] = {1,1}; int Sech(int x) { int i, v; for(i=0;i<G[x].size();i++) { v = G[x][i]; if(vis[v]==0) { vis[v] = 1; if(link[v]==0 || Sech(link[v])) { link[v] = x; link[x] = v; return 1; } } } return 0; } int main(void) { LL i, j; int T, k, sum, ans, s1; for(i=2;i<=2000000;i++) { if(flag[i]) continue; for(j=i*i;j<=2000000;j+=i) flag[j] = 1; } scanf("%d", &T); while(T--) { scanf("%d%d", &n, &k); for(i=1;i<=n;i++) { scanf("%d", &a[i]); G[i].clear(); } s1 = 0; memset(val, 0, sizeof(val)); for(i=1;i<=n;i++) { if(a[i]==1) s1++; for(j=i+1;j<=n;j++) { if(flag[a[i]+a[j]]==0) { val[i] = val[j] = 1; if(a[i]%2 && a[j]!=1) G[i].push_back(j); else if(a[i]!=1) G[j].push_back(i); } } } ans = sum = 0; memset(link, 0, sizeof(link)); for(i=1;i<=n;i++) { if(a[i]!=1) { memset(vis, 0, sizeof(vis)); sum += Sech(i); } } for(i=1;i<=n;i++) { if(a[i]==1) { memset(vis, 0, sizeof(vis)); sum += Sech(i); } } for(i=1;i<=n;i++) { if(a[link[i]]==1) s1--; } if(k<=sum) printf("%d\n", k*2); else { ans = sum*2; k -= sum; if(k*2<=s1) printf("%d\n", ans+k*2); else { ans += s1/2*2; k -= s1/2; for(i=1;i<=n;i++) { if(k==0) break; if(a[i]==1) { if(link[i]==0 && val[i] && s1%2) { s1 = 0; ans++, k--; } } else if(link[i]==0) { ans += val[i]; k -= val[i]; } } printf("%d\n", ans); } } } return 0; }
原文链接:http://blog.csdn.net/jaihk662/article/details/78424129
阅读全文
0 0
- ZOJ 3988 && 2017CCPC秦皇岛 H:Prime Set(二分匹配)
- ZOJ 3988 && 2017CCPC秦皇岛 H:Prime Set(二分匹配)
- ZOJ 3988 && 2017CCPC秦皇岛 H:Prime Set(二分匹配)
- CCPC.2017秦皇岛站 H-prime set
- CCPC.2017秦皇岛站-重现赛-H(二分匹配)
- ZOJ 3988(ccpc秦皇岛H)
- 2017秦皇岛现场赛H.Prime Set(奇偶二分图 匈牙利算法)
- ZOJ 3988 Prime Set [二分图匹配]
- 2017CCPC秦皇岛H(二分 + 二分图的最大匹配数)
- 2017 CCPC 秦皇岛 & ZOJ 3981
- 2017 CCPC 秦皇岛 & ZOJ 3983
- 2017 CCPC 秦皇岛 & ZOJ 3985
- 2017 CCPC 秦皇岛 & ZOJ 3987
- 2017 CCPC 秦皇岛 & ZOJ 3993
- zoj 3988 Prime Set 【二分图最大匹配 + 思维】
- zoj--3983(CCPC秦皇岛)
- ZOJ 3988 Prime Set(二分图)
- ZOJ 3988 Prime Set (最大匹配)
- ngxin
- java 实现扑克牌洗牌功能
- 【软工视频】软件工程概论
- 求二叉树的高度
- 最大子数组问题
- ZOJ 3988 && 2017CCPC秦皇岛 H:Prime Set(二分匹配)
- SDN:初学SDN的感受和规划
- 产生随机10个1000以内随机整数(从大到小)
- hdu6228-搜索&类似树的重心-Tree
- char,varchar,long varchar
- Oracle之分析函数例子
- 挂号系统 V1.0(下)
- 2017 CCPC 秦皇岛 G题
- 【1701H1】【穆晨】【171105】连续第二十六天总结