Prime Independence LightOJ - 1356 (HK 最大独立集 板子)
题意:给你一组数,求一个最大的子集,要求任意两个的倍数都不是素数倍
题解:将每一个数按照质因数奇偶分开,同为奇偶的肯定是合数倍,在奇偶中刚好是素数倍的建边,跑二分图最大独立集,n - 匹配数就是答案
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<sstream> #include<cmath> #include<cstdlib> #include<queue> #include<map> #include<set> #include<vector> using namespace std; #define LL long long #define INF 0x3f3f3f3f #define eps 1e-10 const int MAXN = 4e4 + 10; const int MOD = 1e9+7; const int MAXX = 500005; int prime[MAXX]; int num[MAXN],pos[MAXX]; int n; void getprime(){ memset(prime,0,sizeof prime); for(int i = 2; i <= MAXX; i++){ if(!prime[i]) prime[++prime[0]] = i; for(int j = 1 ;j <= prime[0] && prime[j] <= MAXX / i; j++){ prime[prime[j] * i] = 1; if(i % prime[j] == 0) break; } } } vector<int>G[MAXN]; int uN; int Mx[MAXN],My[MAXN]; int dx[MAXN],dy[MAXN]; int dis; bool used[MAXN]; void addedge(int u,int v) { G[u].push_back(v); } bool SearchP(){ queue<int>que; dis = INF; memset(dx,-1,sizeof dx); memset(dy,-1,sizeof dy); for(int i = 1; i <= uN; i++){ if(Mx[i] == -1){ que.push(i); dx[i] = 0; } } while(!que.empty()){ int u = que.front(); que.pop(); if(dx[u] > dis) break; int sz = G[u].size(); for(int i = 0; i < sz; i++) { int v = G[u][i]; if(dy[v] == -1) { dy[v] = dx[u] + 1; if(My[v] == -1) dis = dy[v]; else { dx[My[v]] = dy[v] + 1; que.push(My[v]); } } } } return dis != INF; } bool dfs(int u) { int sz = G[u].size(); for (int i = 0; i < sz; i++) { int v = G[u][i]; if(!used[v] && dy[v] == dx[u] + 1) { used[v] = true; if(My[v] != -1 && dy[v] == dis) continue; if(My[v] == -1 || dfs(My[v])) { My[v] = u; Mx[u] = v; return true; } } } return false; } int MaxMatch() { int res = 0; memset(Mx,-1,sizeof Mx); memset(My,-1,sizeof My); while(SearchP()) { memset(used,false,sizeof used); for (int i = 1; i <= uN; i++) { if(Mx[i] == -1 && dfs(i)) res++; } } return res; } int factor[105][2]; int fatcnt; int sum; int getFactors(int x) { fatcnt = 0; int tmp = x; for (int i = 1; prime[i] <= tmp / prime[i]; i++) { factor[fatcnt][1] = 0; if (tmp % prime[i] == 0) { factor[fatcnt][0] = prime[i]; while (tmp % prime[i] == 0) { factor[fatcnt][1] ++; tmp /= prime[i]; sum++; } fatcnt++; } } if(tmp != 1) { factor[fatcnt][0] = tmp; factor[fatcnt++][1] = 1; sum++; } return fatcnt; } void init() { uN = 0; memset(pos,0,sizeof pos); for(int i = 0;i <= n; i++) G[i].clear(); } int main() { getprime(); int t; scanf("%d",&t); int ca = 1; while(t--) { init(); scanf("%d", &n); uN = n; for (int i = 1; i <= n; i++) { scanf("%d", &num[i]); pos[num[i]] = i; } for (int i = 1; i <= n; i++) { sum = 0; int pnum = getFactors(num[i]); for(int k = 0; k < pnum; k++) { if(pos[num[i] / factor[k][0]] != 0) { if(sum & 1) addedge(pos[num[i]],pos[num[i] / factor[k][0]]); else addedge(pos[num[i] / factor[k][0]], pos[num[i]]); } } } printf("Case %d: %d\n",ca++,n - MaxMatch()); } }