首页 > 代码库 > Light OJ 1356 Prime Independence 最大独立集+素数筛选
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 ...x/p3 存在并且他们的质因子个数sum奇偶性不同 连边 HK求最大独立集
#include <cstdio> #include <cstring> #include <queue> #include <cmath> #include <algorithm> using namespace std; const int maxn = 500010; const int maxm = 40010; const int INF = 999999999; struct edge { int v, next; }e[maxn]; bool vis[maxn]; int prime[maxm]; int a[maxm]; int b[maxn]; int p[maxm]; int num[maxm]; int first[maxm], cnt; int cx[maxm], cy[maxm]; int dx[maxm], dy[maxm]; int n, dis; void sieve(int n) { int m = sqrt(n+0.5); memset(vis, 0, sizeof(vis)); vis[0] = vis[1] = 1; for(int i = 2; i <= m; i++) if(!vis[i]) for(int j = i*i; j <= n; j += i) vis[j] = 1; } int get_primes(int n) { sieve(n); int c = 0; for(int i = 2; i <= n; i++) if(!vis[i]) prime[c++] = i; return c; } void AddEdge(int u, int v) { e[cnt].v = v; e[cnt].next = first[u]; first[u] = cnt++; } bool search() { dis = INF; memset(dx, -1, sizeof(dx)); memset(dy, -1, sizeof(dy)); queue <int> Q; for(int i = 1; i <= n; i++) { if(cx[i] == -1 && (num[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 = first[u]; i != -1; i = e[i].next) { int v = e[i].v; if(dy[v] == -1) { dy[v] = dx[u] + 1; if(cy[v] == -1) { dis = dy[v]; } else { dx[cy[v]] = dy[v] + 1; Q.push(cy[v]); } } } } return dis != INF; } bool dfs(int u) { for(int i = first[u]; i != -1; i = e[i].next) { int v = e[i].v; if(dy[v] == dx[u] + 1) { dy[v] = 0; if(cy[v] == -1 || dfs(cy[v])) { cx[u] = v; cy[v] = u; //printf("**%d %d\n", u, v); return true; } } } return false; } int match() { int ans = 0; memset(cx, -1, sizeof(cx)); memset(cy, -1, sizeof(cy)); while(search()) { for(int i = 1; i <= n; i++) { if(cx[i] == -1 && (num[i]&1) && dfs(i)) ans++; } } return ans; } int main() { int cas = 1; int T; scanf("%d", &T); int c = get_primes(500000); while(T--) { scanf("%d", &n); memset(b, 0, sizeof(b)); memset(num, 0, sizeof(num)); memset(first, -1, sizeof(first)); cnt = 0; 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 x = a[i]; int sum = 0; int sum2 = 0; for(int j = 0; j < c && prime[j]*prime[j] <= x; j++) { if(x % prime[j] == 0) { p[sum++] = prime[j]; while(x % prime[j] == 0) { x /= prime[j]; sum2++; } } } if(x > 1) { p[sum++] = x; sum2++; } num[i] = sum2; //printf("***%d\n", sum2); for(int j = 0; j < sum; j++) { int temp = b[a[i]/p[j]]; if(temp > i) continue; if(temp) { if((sum2&1)==(num[temp]&1)) continue; //printf("%d %d\n", i, temp); if((sum2&1)) AddEdge(i, temp); else AddEdge(temp, i); } } } int ans = match(); printf("Case %d: %d\n", cas++, n-ans); } return 0; }
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。