ZOJ3988 Prime Set (匈牙利算法求解)
来源:互联网 发布:京东和淘宝的竞品分析 编辑:程序博客网 时间:2024/06/09 00:29
题目链接:ZOJ - 3988 Prime Set
题意:
- 给出n个数, a[1]~a[n]
- 若a[i]+a[j]是素数,那么称 集合{i, j} 为Prime set
- 给定k, 表示至多从由这n个数组成的Prime set中取出k个集合
- 问:取出的集合合并后,集合的大小最大为多少?(注意,此处集合元素是下标,而不是a[i],{1, 2} U {1, 3} = {1, 2, 3} ,故集合大小为3)
解法:
- 首先,求出所有的Prime Set集合
- 先从中选出 所有的两两不相交的集合, 假设其个数为t(如{1, 3}, {2, 4},这就是求最大匹配数)
- 若 t >= k ,由于每个集合有两个元素所以,答案即为 2*k (因为至多选择出k个两两不相交的集合,而每个集合有两个元素,故为2* k)
- 若 t < k ,即取出所有两两不相交的集合后,还可选择 k-t个未被匹配的元素,先求出未被匹配的元素,假设其个数为 tt, 那么这答案就是 2*t + min(tt, k-t),(因为建图时候,元素i都会与另外一个元素j相连表示{i, j}是Prime set, 若i未被匹配,表示{ i, j}中,j已匹配其他元素,故若选择{i, j}只会得到1个不同元素i)
#include<bits/stdc++.h>#define rep(i,a,b) for(int i=a; i<=b; ++i)#define repp(i,a,b) for(int i=b; i>=a; --i)#define mp make_pair#define pb push_back#define ms(a, b) memset(a, b, sizeof(a))#define Size(x) (int)(x.size())using namespace std;typedef long long ll;typedef pair<int, int> pii;typedef vector<int>vi;const int maxn = 3e3+7;const int maxnn = 2e6+5;int a[maxn], n, kk, p[maxnn];bool prime[maxnn];vector<int>maps[maxn];void getprime(){ kk = 0; int x; int i, j; for(i=2; i<=maxnn-2; ++i){ if(!prime[i]) p[kk++] = i; for(j=0; j<=kk; ++j){ if(i*p[j] > maxnn-2) break; prime[i*p[j]] = 1; if(i%p[j] == 0) break; } } return ;}bool visit[maxn];int mark[maxn];bool dfs(int u){ visit[u] = true; rep(j, 0, Size(maps[u])-1){ int i = maps[u][j]; if(!visit[i]) { visit[i] = true; if(mark[i] == 0 || dfs(mark[i])){ mark[i] = u; mark[u] = i; return true; } } } return false;}int solve(){ int ans=0; rep(i, 1, n){ if(mark[i] != 0 ) continue; rep(j, 0, n) visit[j]=false; if(dfs(i)) ans++; } return ans;}int main(){ //freopen("in.txt", "r", stdin); getprime(); int t; scanf("%d", &t); while(t--){ int k; scanf("%d %d", &n, &k); rep(i, 1, n){ scanf("%d", &a[i]); visit[i] = false; maps[i].clear(); mark[i] = -1; } rep(i, 1, n){ rep(j, i+1, n){ if(!prime[a[i]+a[j]]){ visit[i] = visit[j] = true; mark[i] = mark[j] = 0; maps[i].pb(j); maps[j].pb(i); } } } int ans = solve();//最大完美匹配数 if(ans >= k) printf("%d\n", k*2); else { int x = 0; rep(i, 1, n) { if(!mark[i]) x++; } printf("%d\n", ans*2+min(x, k-ans)); } } return 0;}
阅读全文
0 0
- ZOJ3988 Prime Set (匈牙利算法求解)
- 2017秦皇岛现场赛H.Prime Set(奇偶二分图 匈牙利算法)
- 学习匈牙利算法总结(求解二分图最大匹配)
- 匈牙利算法 求解 完美的牛栏
- 二分图相关概念及匈牙利算法求解最大匹配(附代码实现)
- 过山车(匈牙利算法)
- POJ1274(匈牙利算法)
- 匈牙利算法(转)
- 华为oj素数伴侣,利用匈牙利算法求解
- poj3041 最小点覆盖==二分图最大匹配 匈牙利算法求解最大匹配问题(运用DFS)
- 求解最小生成树——prime算法模板
- 普利姆(Prime)算法
- 【普利姆(Prime)算法】
- 普利姆(Prime)算法
- hdu1054 匈牙利算法(增广路) (附匈牙利算法模板)
- 二分图(匈牙利算法)
- hdu 过山车(匈牙利算法)
- POJ 3692(匈牙利算法)
- 判断一个数是否是回文数
- 待整理技术点
- Android 精进之简述 JVM 基础(二):Java内存区域与内存溢出异常
- 海思OSD
- 第二章 Java内存区域与内存溢出异常
- ZOJ3988 Prime Set (匈牙利算法求解)
- yii AR 分页
- 20171103 echarts
- 洛谷 P3941 入阵曲
- 冈萨雷斯数字图像处理学习5:图像复原和重建2 频率滤波和复原
- Problem executing scripts APT::Update::Post-Invoke-Success 'if /usr/bin/test -w /var/cache/app-info
- Linux 2.6内核Makefile浅析
- 为什么很多人说 Java 不适合编写桌面应用?
- PHP实现开发者模式出现该公众号提供的服务出现故障 请稍后再试解决方法