[hihoCoder] #1158 : 质数相关
时间限制:2000ms
单点时限:1000ms
内存限制:256MB
描述
两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。
输入
第一行为一个数T,为数据组数。之后每组数据包含两行。
第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。
输出
对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。
数据范围
1 ≤ T ≤ 20
集合S内的数两两不同且范围在1到500000之间。
小数据
1 ≤ N ≤ 15
大数据
1 ≤ N ≤ 1000
- 样例输入
-
3 5 2 4 8 16 32 5 2 3 4 6 9 3 1 2 3
- 样例输出
-
Case #1: 3 Case #2: 3 Case #3: 2
编程之美2015初赛第一场第三题,找二分图的最大独立集,大小为:点的个数 - 最大匹配。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int T, N; 5 vector<int> v; 6 vector<vector<int>> graph; 7 vector<int> link; 8 vector<bool> visited; 9 bool *isPrime; 10 11 void getPrime() { 12 isPrime = new bool[500001]; 13 memset(isPrime, true, sizeof(bool) * 500001); 14 isPrime[0] = isPrime[1] = false; 15 for (int i = 2; i * i < 500001; ++i) if (isPrime[i]) { 16 for (int j = 2; i * j < 500001; ++j) isPrime[i * j] = false; 17 } 18 } 19 20 int dfs(int u) { 21 for (auto v : graph[u]) if (!visited[v]) { 22 visited[v] = true; 23 if (link[v] == -1 || dfs(link[v])) { 24 link[v] = u; 25 return 1; 26 } 27 } 28 return 0; 29 } 30 31 int hungary() { 32 int res = 0; 33 for (int i = 0; i < N; ++i) { 34 visited.assign(N + 1, false); 35 res += dfs(i); 36 } 37 return res / 2; 38 } 39 40 int main() { 41 getPrime(); 42 cin >> T; 43 for (int t = 1; t <= T; ++t) { 44 cin >> N; 45 v.resize(N); 46 for (int i = 0; i < N; ++i) { 47 cin >> v[i]; 48 } 49 sort(v.begin(), v.end()); 50 graph.assign(N + 1, vector<int>()); 51 link.assign(N + 1, -1); 52 for (int i = 0; i < N - 1; ++i) { 53 for (int j = i + 1; j < N; ++j) { 54 if (v[j] % v[i] == 0) { 55 int tmp = v[j] / v[i]; 56 if (isPrime[tmp]) { 57 graph[i].push_back(j); 58 graph[j].push_back(i); 59 } 60 } 61 } 62 } 63 cout << "Case #" << t << ": "; 64 int res = hungary(); 65 cout << N - res << endl; 66 } 67 return 0; 68 }