基础数学 1002 LightOJ 1356
来源:互联网 发布:组策略映射网络驱动器 编辑:程序博客网 时间:2024/05/18 12:30
题意:
给你一个集合,找出最大的子集合,
该子集合里任意两个数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 500005vector<int>g[maxn];int um[N],vm[N],n;int dx[N],dy[N],dis;bool vis[N];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 500005bool 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;}
0 0
- 基础数学 1002 LightOJ 1356
- lightoj(基础数学)
- 基础数学1003 LightOJ 1341
- 基础数学1004 LightOJ 1336
- 基础数学1005 LightOJ 1282
- 基础数学1006 LightOJ 1245
- 基础数学1007 LightOJ 1236
- LIGHTOJ 1005(组合数学)
- LightOJ 1095 数学
- LightOJ 1245【数学】
- Lightoj 1098【数学/玄学】
- 【数学】 LightOJ 1234 Harmonic Number
- lightoj 1005 - Rooks 【组合数学】
- lightoj 1005 - Rooks 【组合数学】
- lightoj 1148 - Mad Counting 【数学】
- LightOJ 1297: Largest Box【数学】
- LightOJ 1148 - Mad Counting【数学】
- LightOJ 1043 - Triangle Partitioning【数学】
- 基础数论 1001 LightOJ 1370
- 《代码大全》读书笔记及随想(day01)
- soft raid5阅读笔记之五--同步
- 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
- bzoj2844
- 基础数学 1002 LightOJ 1356
- /bin/bash^M: 坏的解释器: 没有那个文件或目录
- 基础数学1003 LightOJ 1341
- Junit测试出现空指针异常
- Pokémon GO的蝴蝶效应——国内哪些APP借了任天堂的东风?
- 函数指针
- Notification学习
- ActiveMQ简介
- 基础数学1004 LightOJ 1336