Description
A set of integers is called prime independent if none of its member is a prime multiple of another member. An integer a is said to be a prime multipleof b if,
a = b x k (where k is a prime [1])
So, 6 is a prime multiple of 2, but 8 is not. And for example, {2, 8, 17} is prime independent but {2, 8, 16} or {3, 6} are not.
Now, given a set of distinct positive integers, calculate the largest prime independent subset.
Input
Input starts with an integer T (≤ 20), denoting the number of test cases.
Each case starts with an integer N (1 ≤ N ≤ 40000) denoting the size of the set. Next line contains N integers separated by a single space. Each of these N integers are distinct and between 1 and 500000 inclusive.
Output
For each case, print the case number and the size of the largest prime independent subset.
Sample Input
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
感觉超棒的一道题,值得一做。。。挺巧妙的。。。
找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系。
思路:
最大独立集,必然是二分图。
最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建边,考虑到能这样建边的数一定是质因子个数奇偶不同,所以相当于按奇偶区分建立了二分图,然后求二分图最大匹配,得到最大独立集就行了。
#pragma comment(linker, "/STACK:102400000,102400000" #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; #define N 500010 #define M 40010 int a[M],b[N],num[M],factor[1000]; vector<int>mmap[M]; int n; bool vis[M]; int linker[M]; bool dfs(int u) { for(int i=0;i<mmap[u].size();i++) { if(!vis[mmap[u][i]]) { vis[mmap[u][i]]=true; if(linker[ mmap[u][i] ]==-1||dfs(linker[ mmap[u][i] ])) { linker[mmap[u][i]]=u; return true; } } } return false; } int hungary() { int u; int res=0; for(u=1;u<=n;u++) { memset(vis,false,sizeof(vis)); if(dfs(u)) res++; } return res; } void init() { memset(num,0,sizeof(num)); memset(b,0,sizeof(b)); memset(linker,-1,sizeof(linker)); for(int i=1;i<=n;i++) mmap[i].clear(); } int main() { int T,Case,t; scanf("%d",&T); Case=1; while(T--) { scanf("%d",&n); init(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) b[ a[i] ]=i; ///对节点哈希 for(int i=1;i<=n;i++) { t = a[i]; int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积 for(int j=2;t>1&&j<=sqrt(t) ;j++) if(t%j==0) { factor[cnt++] = j; while(t%j==0) t/=j,sum++; } if(t>1) //t有可能是质数 factor[cnt++]=t,sum++; num[i] = sum; for(int j=0;j<cnt;j++) { t = b[ a[i] / factor[j] ]; if(t==0) ///都是奇数或者偶数 continue; if((sum&1)) ///是奇数 作为x部 mmap[i].push_back(t); else ///是偶数 mmap[t].push_back(i); } } printf("Case %d: %d\n",Case++,n-hungary()); } return 0; }
Hopcroft-Karp,数组有点乱。。。
#pragma comment(linker, "/STACK:102400000,102400000" #include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<iostream> #include<algorithm> #include<vector> #include<map> #include<queue> #include<stack> #include<string> #include<map> #include<set> #include<ctime> #define eps 1e-6 #define MAX 100005 #define INF 0x3f3f3f3f #define LL long long #define pii pair<int,int> #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) ///map<int,int>mmap; ///map<int,int >::iterator it; using namespace std; #define N 500010 #define M 40010 int a[N],b[N],num[N],factor[1000]; vector<int>mmap[M]; int um[N],vm[N],n; int dx[M],dy[M],dis; bool vis[M]; bool searchP() { queue<int>q; dis=INF; memset(dx,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=1;i<=n;i++) if(um[i]==-1) { q.push(i); dx[i]=0; } while(!q.empty()) { int u=q.front();q.pop(); if(dx[u]>dis) break; for(int i=0;i<mmap[u].size();i++) { int v = mmap[u][i]; if(dy[v]==-1) { dy[v]=dx[u]+1; if(vm[v]==-1) dis=dy[v]; else { dx[vm[v]]=dy[v]+1; q.push(vm[v]); } } } } return dis!=INF; } bool dfs(int u) { for(int i=0;i<mmap[u].size();i++) { int v = mmap[u][i]; if(!vis[v]&&dy[v]==dx[u]+1) { vis[v]=1; if(vm[v]!=-1&&dy[v]==dis) continue; if(vm[v]==-1||dfs(vm[v])) { vm[v]=u;um[u]=v; return 1; } } } return 0; } int maxMatch() { int res=0; memset(um,-1,sizeof(um)); memset(vm,-1,sizeof(vm)); while(searchP()) { memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) if(um[i]==-1&&dfs(i)) res++; } return res; } void init() { memset(b,-1,sizeof(b)); memset(num,0,sizeof(num)); memset(vm,-1,sizeof(vm)); memset(um,-1,sizeof(um)); for(int i=0;i<=n;i++) mmap[i].clear(); } int main() { int k,kk,t,x,y,z; scanf("%d",&k); kk=0; while(k--) { scanf("%d",&n); init(); for(int i=1;i<=n;i++) scanf("%d",&a[i]); for(int i=1;i<=n;i++) b[ a[i] ]=i; for(int i=1;i<=n;i++) { t = a[i]; int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积 for(int j=2;t>1&&j<=sqrt(t) ;j++) if(t%j==0) { factor[cnt++] = j; while(t%j==0) t/=j,sum++; } if(t>1) //t有可能是质数 factor[cnt++]=t,sum++; num[i] = sum; for(int j=0;j<cnt;j++) { t = b[ a[i] / factor[j] ]; if( t==0 ) ///都是奇数或者偶数 continue; if((sum&1)) ///是奇数 作为x部 mmap[i].push_back(t); else ///是偶数 mmap[t].push_back(i); } } printf("Case %d: %d\n",++kk,n-maxMatch()); } return 0; }