LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)
Posted 谦谦君子,陌上其华
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)相关的知识,希望对你有一定的参考价值。
http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1356
题意:
给出n个数,问最多能选几个数,使得该集合中的任意两个数中其中一个数不是另一个质数倍。
思路:
二分图的最大独立集。
那么怎么建图呢?
我们按照质因数的奇偶性来分成两部分建图,如果两个数是质数倍的关系,那么就连边,最后最大独立集=点数-最大匹配。
对每个数进行质因数分解,存储每个质因数和质因数的总数,比如说P,质因数为x1,x2,x3...接下来我们去看是否存在P/x1,P/x2...是否存在。如果存在的话,首先还要判断一下他们的质因数奇偶性,因为质数倍的数只有一个质因数不同,所以肯定是一奇一偶。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 #include<stack> 10 using namespace std; 11 12 const int maxn=500000+5; 13 const int INF=0x3f3f3f3f; 14 15 int n; 16 int cnt=0; 17 int primes[maxn]; 18 int vis[maxn]; 19 20 vector<int>g[40005]; 21 int um[maxn],vm[maxn]; 22 int dx[maxn],dy[maxn],dis; 23 24 void get_primes() 25 { 26 int m=sqrt(maxn+0.5); 27 for(int i=2;i<=m;i++) 28 { 29 if(!vis[i]) 30 { 31 for(int j=i*i;j<=maxn;j+=i) 32 vis[j]=1; 33 } 34 } 35 for(int i=2;i<=maxn;i++) 36 if(!vis[i]) primes[cnt++]=i; 37 } 38 39 bool searchP() 40 { 41 queue<int>q; 42 dis=INF; 43 memset(dx,-1,sizeof(dx)); 44 memset(dy,-1,sizeof(dy)); 45 for(int i=1;i<=n;i++) 46 if(um[i]==-1) 47 { 48 q.push(i); 49 dx[i]=0; 50 } 51 while(!q.empty()) 52 { 53 int u=q.front();q.pop(); 54 if(dx[u]>dis) break; 55 for(int i=0;i<g[u].size();i++) 56 { 57 int v = g[u][i]; 58 if(dy[v]==-1) 59 { 60 dy[v]=dx[u]+1; 61 if(vm[v]==-1) dis=dy[v]; 62 else 63 { 64 dx[vm[v]]=dy[v]+1; 65 q.push(vm[v]); 66 } 67 } 68 } 69 } 70 return dis!=INF; 71 } 72 73 bool dfs(int u) 74 { 75 for(int i=0;i<g[u].size();i++) 76 { 77 int v = g[u][i]; 78 if(!vis[v]&&dy[v]==dx[u]+1) 79 { 80 vis[v]=1; 81 if(vm[v]!=-1&&dy[v]==dis) continue; 82 if(vm[v]==-1||dfs(vm[v])) 83 { 84 vm[v]=u;um[u]=v; 85 return 1; 86 } 87 } 88 } 89 return 0; 90 } 91 92 int maxMatch() 93 { 94 int res=0; 95 memset(um,-1,sizeof(um)); 96 memset(vm,-1,sizeof(vm)); 97 while(searchP()) 98 { 99 memset(vis,0,sizeof(vis)); 100 for(int i=1;i<=n;i++) 101 if(um[i]==-1&&dfs(i)) res++; 102 } 103 return res; 104 } 105 106 int a[maxn],b[maxn],p[maxn],num[maxn]; 107 108 int main() 109 { 110 //freopen("D:\\input.txt","r",stdin); 111 int T; 112 int kase=0; 113 get_primes(); 114 scanf("%d",&T); 115 while(T--) 116 { 117 scanf("%d",&n); 118 for(int i=0;i<=n;i++) g[i].clear(); 119 memset(b,-1,sizeof(b)); 120 for(int i=1;i<=n;i++) 121 scanf("%d",&a[i]); 122 sort(a+1,a+1+n); 123 for(int i=1;i<=n;i++) 124 b[a[i]]=i; 125 126 memset(num,0,sizeof(num)); 127 for(int i=1;i<=n;i++) 128 { 129 int x=a[i]; 130 int sum1=0; 131 int sum2=0; 132 for(int j=0;primes[j]*primes[j]<=x;j++) 133 { 134 if(x%primes[j]==0) 135 { 136 p[sum1++]=primes[j]; 137 while(x%primes[j]==0) {x/=primes[j];sum2++;} 138 } 139 } 140 if(x>1) {p[sum1++]=x;sum2++;} 141 num[i]=sum2; 142 for(int j=0;j<sum1;j++) 143 { 144 int t=b[a[i]/p[j]]; 145 if(t<i&&t>0) 146 { 147 if((sum2&1)==(num[t]&1)) continue; 148 if(sum2&1) g[i].push_back(t); 149 else g[t].push_back(i); 150 } 151 } 152 } 153 154 printf("Case %d: %d\n",++kase,n-maxMatch()); 155 } 156 157 return 0; 158 }
以上是关于LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)的主要内容,如果未能解决你的问题,请参考以下文章
LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)