Prime Independence
大致题意:
对于给定集合,求解最大的子集合,使得集合内两两之商不为质数
解题思路:
求最大独立集,考虑如何建二分图
每个数要么是奇数个素数乘级,要么是偶数个素数乘级,将奇数个素数乘级与偶数个素数乘级连线建图
匈牙利算法有些优化,不然会被T
AC代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6 + 10;
int n;
vector<int>fac[N];
int a[N], id[N], cnt[N];
int match[N], vis[N];
vector<int>g[N];
int tt;
bool find(int x) {
for (int i = 0; i < g[x].size(); ++i) {
int v = g[x][i];
if (vis[v] == tt)continue;
vis[v] = tt;
if (match[v] == -1 || find(match[v])) {
match[v] = x;
return true;
}
}
return false;
}
int main(void)
{
int t; scanf("%d", &t);
for (int T = 1; T <= t; ++T) {
scanf("%d", &n);
//初始化
for (int i = 1; i <= n; ++i) {
g[i].clear(); fac[i].clear();
match[i] = -1;
cnt[i] = 0;
}
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
id[a[i]] = i; //离散
int x = a[i];
//分解质因数
for (int j = 2; j <= x / j; ++j)
if (x % j == 0) {
while (x % j == 0)x /= j, cnt[i]++;
fac[i].push_back(j);
}
if (x > 1)fac[i].push_back(x), cnt[i]++;
}
//建二分图
for (int i = 1; i <= n; ++i)
for (int j = 0; j < (int)fac[i].size(); ++j) {
int x = a[i] / fac[i][j];
if (id[x]) {
int tmp = id[x];
if (cnt[i] & 1)g[i].push_back(tmp);
else g[tmp].push_back(i);
}
}
//匈牙利算法
int res = 0;
for (int i = 1; i <= n; ++i) {
tt++;
if (find(i))res++;
id[a[i]] = 0; //清空离散值
}
printf("Case %d: %d\n", T, n - res);
}
return 0;
}