题目链接: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;
}