基础数学 1002 LightOJ 1356
2016-07-21 20:45
399 查看
题意:
给你一个集合,找出最大的子集合,
该子集合里任意两个数x,y不能存在y/x=t,t是质数
思路:
因为是求最大独立集,所以容易想到二分图来建图
二分图左边放奇数个质因子的数,右边放偶数个质因子的数
然后如果y/x=t,t是质数,就把xy连边,一边二分图匹配就出来了
因为匈牙利的时间复杂度比较高,所以这里用Hopcroft-Carp
大概是O(sqrt(V)*E)
给你一个集合,找出最大的子集合,
该子集合里任意两个数x,y不能存在y/x=t,t是质数
思路:
因为是求最大独立集,所以容易想到二分图来建图
二分图左边放奇数个质因子的数,右边放偶数个质因子的数
然后如果y/x=t,t是质数,就把xy连边,一边二分图匹配就出来了
因为匈牙利的时间复杂度比较高,所以这里用Hopcroft-Carp
大概是O(sqrt(V)*E)
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> #include<queue> #include<stack> #include<string> #include<vector> #include<map> #include<set> using namespace std; #define lowbit(x) (x&(-x)) typedef long long LL; const int maxn = 40005; const int inf=(1<<28)-1; #define N 500005 vector<int>g[maxn]; int um ,vm ,n; int dx ,dy ,dis; bool vis ; void inserts(int u, int v) { g[u].push_back(v); } 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<g[u].size();i++) { int v = g[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<g[u].size();i++) { int v = g[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(vm,-1,sizeof(vm)); memset(um,-1,sizeof(um)); for(int i=0;i<=n;i++) g[i].clear(); } #define maxp 500005 bool notprime[maxp]; int primes[maxp]; void get_prime() { notprime[1]=true; for(int i=2;i<maxp;++i) if(!notprime[i]) { primes[++primes[0]]=i; for(LL j=(LL)i*i;j<maxp;j+=i) notprime[j]=true; } } int A[maxn],B[maxp],Fac[105]; int main() { get_prime(); int Case=0,T; scanf("%d",&T); while(T--) { scanf("%d",&n); init(); memset(B,-1,sizeof(B)); for(int i=1;i<=n;++i) scanf("%d",&A[i]); sort(A+1,A+n+1); for(int i=1;i<=n;++i) B[A[i]]=i; for(int i=1;i<=n;++i) { int t=A[i],Cnt=0,Cnt2=0; for(int j=1;primes[j]*primes[j]<=t;++j) if(t%primes[j]==0) { t/=primes[j]; Fac[Cnt++]=primes[j]; Cnt2++; while(t%primes[j]==0) t/=primes[j],Cnt2++; } if(t>1) Fac[Cnt++]=t,Cnt2++; for(int j=0;j<Cnt;++j) { t=B[A[i]/Fac[j]]; if(t<=i&&t!=-1) { if(Cnt2&1) inserts(i,t); else inserts(t,i); } } } printf("Case %d: %d\n",++Case,n-maxMatch()); } return 0; }
相关文章推荐
- 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
- 自定义注解
- bzoj2844
- Java IO操作——System类对IO的支持(System.out、System.err、System.in)
- CSS样式:cursor -----定义鼠标指针
- poj2686 状压dp
- soft raid5阅读笔记之五--同步
- 基础数论 1001 LightOJ 1370
- fineUI ueditor(可能别的editor也有)配置注意事项
- Guacamole之本地安装Guacamole(二)
- Codeforces 580 B-----二分
- The Text Splitting
- bulb
- 广义径向基神经网络
- ERROR Cannot determine the location of the VS Common Tools Folder
- IP分片
- c语言实现字符串的分割
- 安装CentOS 7.2操作系统
- 关于AsyncHttpClient使用
- 计算机启动过程(转)