2015编程之美 初赛第一场C题 质数相关 二分图的最大匹配
质数相关
Time Limit: 1 Sec Memory Limit: 256 MB
题目连接
http://hihocoder.com/contest/msbop2015round2a/problem/3Description
两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。
Input
第一行为一个数T,为数据组数。之后每组数据包含两行。
第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。
Output
对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。
Sample Input
3
5
2 4 8 16 32
5
2 3 4 6 9
3
1 2 3
5
2 4 8 16 32
5
2 3 4 6 9
3
1 2 3
Sample Output
Case #1: 3
Case #2: 3
Case #3: 2
Case #2: 3
Case #3: 2
HINT
1 ≤ T ≤ 20
集合S内的数两两不同且范围在1到500000之间。
小数据
1 ≤ N ≤ 15
大数据
1 ≤ N ≤ 1000
题意
题解:
首先我们把题目转化一下,我们由所给的质数关系,我们可以得到 每一个数可以和哪些数在一起的图
然后我们就可以转化成二分图的最大匹配了!
唔 另一道题可见:http://www.cnblogs.com/qscqesze/p/4414246.html
代码:
//qscqesze #include <cstdio> #include <cmath> #include <cstring> #include <ctime> #include <iostream> #include <algorithm> #include <set> #include <vector> #include <sstream> #include <queue> #include <typeinfo> #include <fstream> #include <map> #include <stack> typedef long long ll; using namespace std; //freopen("D.in","r",stdin); //freopen("D.out","w",stdout); #define sspeed ios_base::sync_with_stdio(0);cin.tie(0) #define maxn 200001 #define mod 10007 #define eps 1e-9 int Num; char CH[20]; //const int inf=0x7fffffff; //нчоч╢С const int inf=0x3f3f3f3f; /* inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } */ //************************************************************************************** inline ll read() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } inline void P(int x) { Num=0;if(!x){putchar('0');puts("");return;} while(x>0)CH[++Num]=x%10,x/=10; while(Num)putchar(CH[Num--]+48); puts(""); } const int MAXN = 500001; bool flag[MAXN]; int primes[MAXN], pi; void GetPrime_1() { int i, j; pi = 0; memset(flag, false, sizeof(flag)); for (i = 2; i < MAXN; i++) if (!flag[i]) { primes[i] = 1;//素数标识为1 for (j = i; j < MAXN; j += i) flag[j] = true; } } vector<int> q[maxn]; int vis[maxn]; int match[maxn]; int a[maxn]; bool cmp(int b,int c) { return b>c; } int dfs(int x) { for(int i=0;i<q[x].size();i++) { if(vis[q[x][i]]==0) { vis[q[x][i]]=1; if(match[q[x][i]]==-1||dfs(match[q[x][i]])) { match[q[x][i]]=x; return 1; } } } return 0; } int main() { GetPrime_1(); primes[1]=0; int t=read(); for(int cas=1;cas<=t;cas++) { memset(match,-1,sizeof(match)); int n=read(); for(int i=0;i<n;i++) q[i].clear(); for(int i=0;i<n;i++) a[i]=read(); sort(a,a+n,cmp); for(int i=0;i<n;i++) { for(int j=0;j<n;j++) { if(i==j) continue; int b=a[j]; int c=a[i]; if(b<c) swap(b,c); if(b%c==0&&primes[b/c]) { q[j].push_back(i); } } } int ans=0; for(int i=0;i<n;i++) { memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } printf("Case #%d: %d\n",cas,n-ans/2); } }