题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3335
【题意】给定N个数,范围0 .. 2^61-1,求最多能选出多少个数,他们相互不能整除。
【分析】除去重复的数,根据整除关系建图,可知它是一个树,进而也是一个二分图。求最大独立集或者最小路径覆盖。
最小路径覆盖 = N - 最大匹配 = 最大独立集


1 #include<stdio.h> 2 #include<math.h> 3 #include<string.h> 4 #include<algorithm> 5 using namespace std; 6 7 #define LL long long 8 9 const int maxn = 1010; 10 11 int n; 12 LL a[maxn]; 13 bool mp[maxn][maxn]; 14 bool vis[maxn]; 15 int match[maxn]; 16 bool dfs(int u) 17 { 18 for (int i=1;i<=n;i++) 19 { 20 if (!vis[i] && mp[u][i]) 21 { 22 vis[i] = 1; 23 if(match[i] == -1 || dfs(match[i])) 24 { 25 match[i] = u; 26 return true; 27 } 28 } 29 } 30 return false; 31 } 32 int solve() 33 { 34 memset(match, -1 ,sizeof(match)); 35 int res = 0; 36 for (int i=1;i<=n;i++) 37 { 38 memset(vis, 0 ,sizeof(vis)); 39 if (dfs(i)) 40 { 41 res++; 42 } 43 } 44 return res; 45 } 46 int main() 47 { 48 int cas; 49 scanf("%d",&cas); 50 while (cas--) 51 { 52 scanf("%d",&n); 53 for (int i=1;i<=n;i++) 54 { 55 scanf("%I64d",&a[i]); 56 } 57 sort(a+1,a+1+n); 58 int nn = 1; 59 for (int i=2;i<=n;i++) 60 { 61 if (a[i]==a[nn]) 62 { 63 64 }else{ 65 a[++nn] = a[i]; 66 } 67 } 68 n = nn; 69 memset(mp, 0, sizeof(mp)); 70 for (int i=1;i<=n;i++) 71 { 72 for (int j=i+1;j<=n;j++) 73 { 74 if (a[j] % a[i]==0) 75 { 76 mp[i][j] = 1; 77 } 78 } 79 } 80 81 printf("%d\n", n - solve()); 82 } 83 return 0; 84 }