题目描述:
两个数a和b(a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。
思路:
最大独立集,大致分析了一下感觉是二分图,没有详细证明,不过大数据过了,应该是对的吧,求大神证明是二分图。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 1001; 7 const int M = 500001; 8 const int E = 100000; 9 bool prime[M]; 10 bool visit[N]; 11 int head[N]; 12 int mark[N]; 13 int label[N]; 14 int n, e; 15 16 struct Edge 17 { 18 int v, next; 19 } edge[E]; 20 21 void init() 22 { 23 e = 0; 24 memset( head, -1, sizeof(head) ); 25 } 26 27 void addEdge( int u, int v ) 28 { 29 edge[e].v = v; 30 edge[e].next = head[u]; 31 head[u] = e++; 32 } 33 34 int dfs( int u ) 35 { 36 for ( int i = head[u]; i != -1; i = edge[i].next ) 37 { 38 int v = edge[i].v; 39 if ( !visit[v] ) 40 { 41 visit[v] = true; 42 if ( mark[v] == -1 || dfs( mark[v] ) ) 43 { 44 mark[v] = u; 45 mark[u] = v; 46 return 1; 47 } 48 } 49 } 50 return 0; 51 } 52 53 int hunagry() 54 { 55 memset( mark, -1, sizeof(mark) ); 56 int res = 0; 57 for ( int i = 1; i <= n; i++ ) 58 { 59 if ( mark[i] != -1 ) continue; 60 memset( visit, 0, sizeof(visit) ); 61 res += dfs(i); 62 } 63 return res; 64 } 65 66 void get() 67 { 68 memset( prime, true, sizeof(prime) ); 69 prime[0] = prime[1] = false; 70 for ( int i = 2; i < M; i++ ) 71 { 72 if ( prime[i] ) 73 { 74 int j = i * i; 75 if ( j >= M ) break; 76 do 77 { 78 prime[j] = false; 79 j += i; 80 } while ( j < M ); 81 } 82 } 83 } 84 85 int main() 86 { 87 get(); 88 int t; 89 scanf("%d", &t); 90 for ( int _case = 1; _case <= t; _case++ ) 91 { 92 scanf("%d", &n); 93 init(); 94 for ( int i = 1; i <= n; i++ ) 95 { 96 scanf("%d", label + i); 97 for ( int j = i - 1; j > 0; j-- ) 98 { 99 int tx = label[i], ty = label[j]; 100 if ( tx > ty ) swap( tx, ty ); 101 if ( ty % tx ) continue; 102 int r = ty / tx; 103 if ( prime[r] ) 104 { 105 addEdge( i, j ); 106 addEdge( j, i ); 107 } 108 } 109 } 110 printf("Case #%d: %d ", _case, n - hunagry()); 111 } 112 return 0; 113 }