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 }

 

posted @ 2017-05-07 10:22  Kayden_Cheung  阅读(491)  评论(0编辑  收藏  举报
//目录