UVA1151BuyOrBuild

来源:互联网 发布:linux修改文件内容 编辑:程序博客网 时间:2024/06/11 10:11
//UVA1151BuyOrBuild#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;const int maxq = 8 + 2;const int maxn = 1000 + 10;int cost[maxq], x[maxn], y[maxn], p[maxn];int n, q;vector<int> subq[maxq];struct Edge {int u, v, c;Edge(int u, int v, int c) : u(u), v(v), c(c) {}bool operator < (const Edge& rhs) const {    return c < rhs.c;}};int findset(int x) {return x == p[x] ? x : findset(p[x]);} int MST(int cnt, const vector<Edge>& e) {int m = e.size(), spend = 0;for(int i = 0; i < m; i++) {int x = findset(e[i].u), y = findset(e[i].v);if(x != y) {p[x] = y;spend += e[i].c;if(--cnt == 1) return spend;}}return 0;}int main() {int T;scanf("%d", &T);while(T--) {int cnt;scanf("%d%d", &n, &q);for(int i = 0; i < q; i++) {scanf("%d%d", &cnt, &cost[i]);subq[i].clear();for(int j = 0; j < cnt; j++) {int id; scanf("%d", &id);subq[i].push_back(id - 1);}}vector<Edge> e;for(int i = 0; i < n; i++) scanf("%d%d", &x[i], &y[i]);for(int i = 0; i < n; i++)     for(int j = i + 1; j < n; j++) {    int c = (x[i] - x[j]) * (x[i] - x[j]) + (y[i] - y[j]) * (y[i] - y[j]);    e.push_back(Edge(i, j, c));     }cnt = n;    sort(e.begin(), e.end());    for(int i = 0; i < n; i++) p[i] = i;int ans = MST(cnt, e);for(int subset = 1; subset < (1 << q) - 1; subset++) {cnt = n;int spend  = 0;for(int i = 0; i < n; i++) p[i] = i;for(int i = 0; i < q; i++) if(subset & (1 << i)) {spend += cost[i];for(int j = 0; j < subq[i].size(); j++) {int x = findset(subq[i][j]), y = findset(subq[i][0]);if(x != y) {p[x] = y;cnt--;}//对每一种已选择的连通分量,构建并查集 }}ans = min(ans, spend + MST(cnt, e));}printf("%d\n", ans);if(T) printf("\n");}return 0;}/*17 32 4 1 23 3 3 6 73 9 2 4 50 24 02 04 21 30 54 4*/

原创粉丝点击