很明显的最大独立集, 预处理出矛盾边
点数1000个,用HK算法保险
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
const int N = 1005;
const int INF = 0x3f3f3f3f;
bool bmask[N];
int nx, ny, dis;
int cx[N], cy[N];
int dx[N], dy[N];
vector<int> g[N];
bool searchpath() {
queue<int> Q;
dis = INF;
memset(dx, -1, sizeof(dx));
memset(dy, -1, sizeof(dy));
for(int i = 0; i < nx; i++) {
if(cx[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 = 0; i < g[u].size(); i++) {
int v = g[u][i];
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 findpath(int u) {
for(int i = 0; i < g[u].size(); i++) {
int v = g[u][i];
if(!bmask[v] && dy[v] == dx[u] + 1) {
bmask[v] = 1;
if(cy[v] != -1 && dy[v] == dis)
continue;
if(cy[v] == -1 || findpath(cy[v])) {
cy[v] = u; cx[u] = v;
return true;
}
}
}
return false;
}
int MaxMatch() {
int res = 0;
memset(cx, -1, sizeof(cx));
memset(cy, -1, sizeof(cy));
while(searchpath()) {
memset(bmask, 0, sizeof(bmask));
for(int i = 0; i < nx; i++) {
if(cx[i] == -1)
res += findpath(i);
}
}
return res;
}
int t, n, a[N];
int vis[500005];
int main() {
int cas = 0;
vis[0] = vis[1] = 1;
for (int i = 2; i <= 500000; i++) {
if (i * i > 500000) break;
for (int j = i * i; j <= 500000; j += i)
vis[j] = 1;
}
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
nx = ny = n;
for (int i = 0; i < n; i++) scanf("%d", &a[i]);
sort(a, a + n);
for (int i = 0; i < n; i++) g[i].clear();
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (a[j] % a[i] == 0 && vis[a[j] / a[i]] == 0) {
g[i].push_back(j);
g[j].push_back(i);
};
}
}
printf("Case #%d: %d\n", ++cas, n - MaxMatch() / 2);
}
return 0;
}