题干:
给你n个数,求一个最大集合,使集合内各个数之间没有整除关系,求集合中最多能有多少个数。
n<=1000,每个数的范围为[1,
2
64
2^{64}
264-1].
思路:
独立集:指一个图中两两不相邻的点构成的集合。
最小顶点覆盖:选择最少的顶点能覆盖所有的边,即从原图中任选一条边,至少有一个顶点属于这个顶点集合。
在二分图中,最大匹配数=最小顶点覆盖数
最大独立集=定点数-最小顶点覆盖数
二分图的最大匹配可以用匈牙利算法求得
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;
ll x[1100];
int a[1100][1100],book[1100],vis[1100],n;
bool dfs(int pos)
{
for(int i=0;i<n;i++){
if(a[pos][i]&&vis[i]==0)
{
vis[i]=1;
//printf("%d\n",i);
if(book[i]==-1||dfs(book[i])) //搜索是否可以腾位置
{
book[i]=pos;
return true;
}
}
}
return false;
}
int hungary() //匈牙利算法
{
int ans=0;
memset(book,-1,sizeof(book));
for(int i=0;i<n;i++){
memset(vis,0,sizeof(vis));
if(dfs(i))
ans++;
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
memset(a,0,sizeof(a));
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lld",&x[i]);
sort(x,x+n);
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
if(x[j]%x[i]==0)
a[i][j]=1; //建图
}
}
printf("%d\n",n-hungary()); //求最大独立集
}
return 0;
}