1. 程式人生 > >Prime Independence LightOJ - 1356(二分圖匹配+最大獨立集)

Prime Independence LightOJ - 1356(二分圖匹配+最大獨立集)

題目連結:qaq

 

 

 

題意:給你一堆數,讓你找出最大一組數裡面不存在一個整數是另一個整數的素數倍,輸出最大數量。

 

思路:將數按質因子的數量奇偶分邊,然後將素數倍兩個整數=連邊。最後就是求最大獨立集的方法了

 

附上程式碼:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<queue>
#include<algorithm>
using namespace std;
const int MAXN = 500010;
int prime[MAXN + 1];
int bn[40010];
int vis[MAXN];
int nnum[40010];
int ax[MAXN];
int sum = 0;
const int N = 40100;
const int inf = 0x3f3f3f3f;
struct edge {
	int to, next;
}g[N * 20];
int match[N], head[N];
bool used[N];
int nx, ny, cnt, dis;
int dx[N], dy[N], cx[N], cy[N];
void add_edge(int v, int u) {
	g[cnt].to = u, g[cnt].next = head[v], head[v] = cnt++;
}
bool bfs() {
	queue<int>que;
	dis = inf;
	memset(dx, -1, sizeof(dx));
	memset(dy, -1, sizeof(dy));
	for (int i = 1; i <= nx; i++) {
		if (cx[i] == -1) {
			que.push(i);
			dx[i] = 0;
		}
	}
	while (!que.empty()) {
		int v = que.front();
		que.pop();
		if (dx[v]>dis) break;
		for (int i = head[v]; i != -1; i = g[i].next) {
			int u = g[i].to;
			if (dy[u] == -1) {
				dy[u] = dx[v] + 1;
				if (cy[u] == -1)
					dis = dy[u];
				else {
					dx[cy[u]] = dy[u] + 1;
					que.push(cy[u]);
				}
			}
		}
	}
	return  dis != inf;
}
int dfs(int v) {
	for (int i = head[v]; i != -1; i = g[i].next) {
		int u = g[i].to;
		if (!used[u] && dy[u] == dx[v] + 1) {
			used[u] = true;
			if (cy[u] != -1 && dy[u] == dis) continue;
			if (cy[u] == -1 || dfs(cy[u])) {
				cy[u] = v;
				cx[v] = u;
				return 1;
			}
		}
	}
	return 0;
}
int hopcroft_karp() {
	int res = 0;
	memset(cx, -1, sizeof(cx));
	memset(cy, -1, sizeof(cy));
	while (bfs()) {
		memset(used, 0, sizeof(used));
		for (int i = 1; i <= nx; i++) {
			if (cx[i] == -1)
				res += dfs(i);
		}
	}
	return res;
}
void getPrime() {
	memset(prime, 0, sizeof(prime));
	for (int i = 2; i <= MAXN; i++) {
		if (!prime[i])prime[++prime[0]] = i;
		for (int j = 1; j <= prime[0] && prime[j] <= MAXN / i; j++) {
			prime[prime[j] * i] = 1;
			if (i%prime[j] == 0) break;
		}
	}
}
long long factor[100][2];
int fatCnt;
int getFactors(long long x) {
	fatCnt = 0;
	long long 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;
}
int main(void) {
	getPrime();
	int t;
	scanf("%d", &t);
	int ca = 0;
	while (t--) {
		int n;

		cnt = 0;
		memset(ax, 0, sizeof(ax));
		memset(vis, 0, sizeof(vis));
		memset(head, -1, sizeof(head));
		scanf("%d", &n);
		for (int i = 1; i <= n; i++) {
			scanf("%d", &bn[i]);
			ax[bn[i]] = 1;
		}
		nx = n;
		ny = 0;
		sort(bn + 1, bn + n + 1);
		for (int i = 1; i <= n; i++) {
			vis[bn[i]] = i;
		}
		for (int i = 1; i <= n; i++) {
			sum = 0;
			int num = getFactors(bn[i]);
			nnum[i] = num;
			for (int z = 0; z<num; z++) {
				if (ax[bn[i] / factor[z][0]]) {
					//printf("%d %d\n", vis[bn[i]], vis[bn[i] / factor[z][0]]);
					if (sum & 1) {
						add_edge(vis[bn[i]], vis[bn[i] / factor[z][0]]);
					}
					else {
						add_edge(vis[bn[i] / factor[z][0]], vis[bn[i]]);
					}
					//add_edge(vis[bn[i]],vis[bn[i]/factor[z][0]]);
					//add_edge(vis[bn[i]/factor[z][0]],vis[bn[i]]);
				}
			}
		}
		printf("Case %d: %d\n", ++ca, n - hopcroft_karp());
	}
	return 0;
}