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 }
时间: 2024-08-04 18:32:21

LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)的相关文章

LightOJ 1356 Prime Independence (素数 二分图)

Prime Independence Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1356 Description A set of integers is called prime independent if none of its member is a prime multiple of another member. A

LightOJ 1356 Prime Independence 二分图最大独立集,HK算法

这个题唯一需要说的就是普通的匈牙利算法是O(nm)的,过不了 然后HK算法可以O(n^0.5m),这个算法可以每次找很多同样长度的最短增广路 分析见:http://www.hardbird.net/lightoj-1356-prime-independence%E6%9C%80%E5%A4%A7%E7%8B%AC%E7%AB%8B%E9%9B%86-hopcroft-carp%E7%AE%97%E6%B3%95/ #include <cstdio> #include <iostream&

Light OJ 1356 Prime Independence 最大独立集+素数筛选

题目来源:Light OJ 1356 Prime Independence 题意:给你n个数 选出最多的数构成一个集合使得任何2个数不是另外一个数的质数倍 x!=k*y 思路:矛盾的2个数连边 并且所有数分成质因子数为奇数和偶数两部分 以质因子奇偶不同构建二分图 同奇或者同偶的数一定不是另外一个数的质数倍 判断矛盾 首先对每个数因子分解 例如x 有a1个p1质因子 a2个p2质因子...an个pn质因子 x的质因子个数为a1+a2+...+an 记为sum 判断是否存在x/p1  x/p2 ..

poj 1365 Prime Land 质因数分解

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int primeNUM[] = { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,

light_oj 1356 素数独立集,二分图最大独立集

light_oj 1356 素数独立集,二分图最大独立集 B - Prime Independence Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Submit Status Practice LightOJ 1356 Description A set of integers is called prime independent if none of its member is a pr

【BZOJ2227】【ZJOI2011】看电影 [组合数学][质因数分解]

看电影 Time Limit: 10 Sec  Memory Limit: 259 MB[Submit][Status][Discuss] Description 到了难得的假期,小白班上组织大家去看电影.但由于假期里看电影的人太多,很难做到让全班看上同一场电影,最后大家在一个偏僻的小胡同里找到了一家电影院.但这家电影院分配座位的方式很特殊,具体方式如下: 1. 电影院的座位共有K个,并被标号为1…K,每个人买完票后会被随机指定一个座位,具体来说是从1…K中等可能的随机选取一个正整数,设其为L.

质因数分解(0)&lt;P2012_1&gt;

质因数分解 (prime.cpp/c/pas) [问题描述] 已知正整数n是两个不同的质数的乘积,试求出较大的那个质数. [输入] 输入文件名为prime.in. 输入只有一行,包含一个正整数n. [输出] 输出文件名为prime.out. 输出只有一行,包含一个正整数p,即较大的那个质数. [数据范围] 对于60%的数据,6 ≤ n ≤ 1000. 对于100%的数据,6 ≤ n ≤ 2*109.

【BZOJ-4514】数字配对 最大费用最大流 + 质因数分解 + 二分图 + 贪心 + 线性筛

4514: [Sdoi2016]数字配对 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 726  Solved: 309[Submit][Status][Discuss] Description 有 n 种数字,第 i 种数字是 ai.有 bi 个,权值是 ci. 若两个数字 ai.aj 满足,ai 是 aj 的倍数,且 ai/aj 是一个质数, 那么这两个数字可以配对,并获得 ci×cj 的价值. 一个数字只能参与一次配对,可以不参与配对. 在

POJ 1845 Sumdiv#质因数分解+二分

题目链接:http://poj.org/problem?id=1845 关于质因数分解,模板见:http://www.cnblogs.com/atmacmer/p/5285810.html 二分法思想:选定一个要进行比较的目标,在区间[l,r]之间不断二分,直到取到与目标相等的值. #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll