UVa1151 Buy or Build (最小生成树,枚举子集)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa1151 Buy or Build (最小生成树,枚举子集)相关的知识,希望对你有一定的参考价值。
链接:http://bak.vjudge.net/problem/UVA-1151
分析:先在原图上跑一遍MST,得到n-1条边,然后其它的边完全可以抛弃掉,因为它们不会比这n-1条边更优,这样就可以把原图边的数量减少到n-1条,并且得到ans初值。
接下来就是通过枚举套餐子集,生成一个套餐费用c1并且得到若干联通分量,再在这些联通分量基础上跑MST得到最小花费c2,更新答案ans。
1 #include <cstdio> 2 #include <vector> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 1e3 + 5; 7 const int maxq = 8; 8 9 int n, q, cost[maxn], x[maxn], y[maxn]; 10 vector<int> subn[maxq]; 11 12 int pa[maxn]; 13 int findset(int x) { return pa[x] != x ? pa[x] = findset(pa[x]) : x; } 14 15 struct Edge { 16 int u, v, w; 17 Edge(int u, int v, int w): u(u), v(v), w(w) {} 18 bool operator < (const Edge& rhs) const { 19 return w < rhs.w; 20 } 21 }; 22 23 int MST(int cnt, const vector<Edge>& e, vector<Edge>& used) { 24 if (cnt == 1) return 0; 25 int ans = 0; 26 int sz = e.size(); 27 for (int i = 0; i < sz; i++) { 28 int u = findset(e[i].u); int v = findset(e[i].v); 29 if (u != v) { 30 pa[u] = v; 31 ans += e[i].w; 32 used.push_back(e[i]); 33 if (--cnt == 1) break; 34 } 35 } 36 return ans; 37 } 38 39 int main() { 40 int T; 41 scanf("%d", &T); 42 while (T--) { 43 scanf("%d%d", &n, &q); 44 for (int i = 0, cnt, u; i < q; i++) { 45 scanf("%d%d", &cnt, &cost[i]); 46 subn[i].clear(); 47 while (cnt--) { 48 scanf("%d", &u); 49 subn[i].push_back(u - 1); 50 } 51 } 52 for (int i = 0; i < n; i++) scanf("%d%d", &x[i], &y[i]); 53 vector<Edge> e, need; 54 for (int i = 0; i < n; i++) 55 for (int j = i + 1; j < n; j++) { 56 int d = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]); 57 e.push_back(Edge(i, j, d)); 58 } 59 for (int i = 0; i < n; i++) pa[i] = i; 60 sort(e.begin(), e.end()); 61 int ans = MST(n, e, need); 62 for (int mask = 0; mask < (1 << q); mask++) { 63 for (int i = 0; i < n; i++) pa[i] = i; 64 int cnt = n, c = 0; 65 for (int i = 0; i < q; i++) if (mask & (1 << i)) { 66 c += cost[i]; 67 for (int j = 1; j < subn[i].size(); j++) { 68 int u = findset(subn[i][j]), v = findset(subn[i][0]); 69 if (u != v) { 70 pa[u] = v; 71 cnt--; 72 } 73 } 74 } 75 vector<Edge> dummy; 76 ans = min(ans, c + MST(cnt, need, dummy)); 77 } 78 printf("%d\n", ans); 79 if (T) putchar(‘\n‘); 80 } 81 return 0; 82 }
以上是关于UVa1151 Buy or Build (最小生成树,枚举子集)的主要内容,如果未能解决你的问题,请参考以下文章
uva 1151Buy or Build(图论 最小生成树)
UVa 1151 Buy or Build (最小生成树+二进制法暴力求解)