UVa1151 Buy or Build
填坑(p.358)
以前天真的以为用prim把n-1条边求出来就可以
现在看来是我想多了
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<algorithm> 5 #include<iostream> 6 7 const int N = 1000 + 10; 8 9 struct Node { 10 int x, y; 11 Node(int x = 0, int y = 0) : x(x), y(y) {} 12 }p[N]; 13 14 int sqr(int x) { 15 return x * x; 16 } 17 18 int dist(const Node& a, const Node& b) { 19 return sqr(a.x - b.x) + sqr(a.y - b.y); 20 } 21 22 struct Edge { 23 int u, v, w; 24 Edge() {} 25 Edge(int u, int v, int w) : u(u), v(v), w(w) {} 26 bool operator < (const Edge& rhs) const { 27 return w < rhs.w; 28 } 29 }; 30 #include<vector> 31 std::vector<Edge> edges, pree; 32 33 int n, ans; 34 int d[N], pre[N], dis[N][N]; 35 bool inMST[N]; 36 37 void prim() { 38 memset(d, 0x3f, sizeof d); 39 memset(inMST, 0, sizeof inMST); 40 ans = d[0] = 0; 41 for(int i = 0; i < n; i++) { 42 int u = -1; 43 for(int v = 0; v < n; v++) if(!inMST[v]) { 44 if(u == -1 || d[v] < d[u]) u = v; 45 } 46 inMST[u] = 1; 47 ans += d[u]; 48 if(i) edges.push_back(Edge(u, pre[u], dis[u][pre[u]])); 49 for(int v = 0; v < n; v++) if(!inMST[v]) { 50 if(d[v] > d[u] + dis[u][v]) { 51 d[v] = d[u] + dis[u][v]; 52 pre[v] = u; 53 } 54 } 55 } 56 } 57 58 int fa[N]; 59 int find(int x) { 60 return fa[x] == x ? x : fa[x] = find(fa[x]); 61 } 62 63 bool merge(int x, int y) { 64 x = find(x), y = find(y); 65 if(x == y) return 0; 66 return fa[x] = y, 1; 67 } 68 69 void UFS_init() { 70 for(int i = 0; i < n; i++) fa[i] = i; 71 } 72 73 void pre_kruskal() { 74 for(int i = 0; i < n; i++) { 75 for(int j = i + 1; j < n; j++) { 76 pree.push_back(Edge(i, j, dis[i][j])); 77 } 78 } 79 sort(pree.begin(), pree.end()); 80 81 UFS_init(); 82 int MST = n; 83 ans = 0; 84 for(unsigned i = 0; i < pree.size(); i++) { 85 const Edge& e = pree[i]; 86 if(merge(e.u, e.v)) { 87 edges.push_back(e); 88 ans += e.w; 89 if(--MST == 1) break; 90 } 91 } 92 } 93 94 int q; 95 #include<vector> 96 std::vector<int> frees[10]; 97 int cost[10]; 98 #include<cassert> 99 void Kruskal(int mask) { 100 UFS_init(); 101 int MST = n, res = 0; 102 for(int j = 0; j < q; j++) if(mask >> j & 1) { 103 res += cost[j]; 104 for(unsigned i = 1; i < frees[j].size(); i++) { 105 MST -= merge(frees[j][i-1], frees[j][i]); 106 } 107 } 108 109 for(unsigned i = 0; i < edges.size(); i++) { 110 if(MST == 1) break; 111 if(merge(edges[i].u, edges[i].v)) res += edges[i].w, MST--; 112 } 113 assert(MST == 1); 114 ans = std::min(ans, res); 115 } 116 117 int main() { 118 #ifdef DEBUG 119 freopen("in.txt", "r", stdin); 120 freopen("out.txt", "w", stdout); 121 #endif 122 123 int T; scanf("%d", &T); 124 while(T--) { 125 pree.clear(); 126 edges.clear(); 127 scanf("%d%d", &n, &q); 128 for(int i = 0; i < q; i++) { 129 int m; 130 scanf("%d%d", &m, cost + i); 131 frees[i].resize(m); 132 for(int j = 0; j < m; j++) { 133 scanf("%d", &frees[i][j]); 134 --frees[i][j]; 135 } 136 } 137 for(int i = 0; i < n; i++) { 138 scanf("%d%d", &p[i].x, &p[i].y); 139 for(int j = 0; j < i; j++) { 140 dis[i][j] = dis[j][i] = dist(p[i], p[j]); 141 } 142 } 143 pre_kruskal(); 144 std::sort(edges.begin(), edges.end()); 145 for(int mask = 0; mask < (1 << q); mask++) { 146 Kruskal(mask); 147 } 148 149 printf("%d\n", ans); 150 if(T) puts(""); 151 } 152 153 return 0; 154 }
原文出处http://www.cnblogs.com/showson/