UVa 1151 Buy or Build
来源:互联网 发布:蜜桃tv源码 编辑:程序博客网 时间:2024/05/17 10:56
来源:《算法竞赛入门经典》(第二版)例题11-3、UVa 1151
题目描述:
给定n个结点和q个子网络,每个子网络有若干结点,如果要关联,则需花费一定费用.现在要让n个结点互相关联,除了通过子网络外,还可直接连通路,耗费是两者距离的平方.求达到目标的最小花费.
题目分析:
子网络数目上限只有8个,可以生成选取子集来枚举.当n个结点给定后,这个图是一个完全图,可以预先通过Kruskal得到什么网络都不选的最小生成树,注意到这时被排除的边以后也不可能再用.接下来对每种可能的子网路选法,将子网络中边加入之前由最小生成树的边集中,再做一次最小生成树求解.
使用vector的版本(70ms)
// Created by wander on 16/6/2.// Copyright © 2016年 W4anD0eR96. All rights reserved.// UVa 1151 Buy or Build// 类型:图论-生成树#include "bits/stdc++.h"using namespace std;int kase, n, m, p[1050], res;struct Edge { int u, v, w; };bool f(const Edge& a, const Edge& b) { return a.w < b.w; }vector<Edge> e;pair<int, int> pos[1050];struct SubNet { int c, n, no[1050]; }sub[15];int Dist(pair<int, int> a, pair<int, int> b) { return (a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second);}int Find(int x) { return (p[x] != x) ? (p[x] = Find(p[x])) : x; }int main(){#ifdef DEBUG freopen("in", "r", stdin); freopen("out", "w", stdout);#endif scanf("%d", &kase); while (kase--) { e.clear(); scanf("%d%d",&n,&m); for (int i = 0 ; i < m ; i += 1){ scanf("%d%d",&sub[i].n, &sub[i].c); for(int j = 0 ; j < sub[i].n ; j += 1) scanf("%d", &sub[i].no[j]); } for(int i = 1 ; i <= n ; i += 1) { scanf("%d%d", &pos[i].first, &pos[i].second); for(int j = 1 ; j < i; j += 1) e.push_back((Edge){j, i, Dist(pos[i], pos[j])}); } sort(e.begin(), e.end(), f); res = 0; for(int i = 0 ; i <= n ; i += 1) p[i] = i; for (int i = 0, cnt = 0; cnt < n - 1; i += 1) { int x = Find(e[i].u), y = Find(e[i].v); if (x != y) { res += e[i].w; p[x] = y; e[cnt] = e[i]; cnt += 1; } } e.resize(n - 1); for (int state = 1; state < (1 << q) ; state += 1) { int cnt = 0, t = 0; for (int i = 0 ; i <= n; i += 1) p[i] = i; for (int i = 0 ; i < q; i += 1) if ((state >> i) & 1) { t += sub[i].c; for (int k = 1 ; k < sub[i].n ; k += 1) { int x = Find(sub[i].no[k]), y = Find(sub[i].no[k - 1]); if (x != y) { p[x] = y; cnt += 1; } } } for (int i = 0; cnt < n - 1; i += 1) { int x = Find(e[i].u), y = Find(e[i].v); if (x != y) { t += e[i].w; p[x] = y; cnt += 1; } } res = min(res, t); } printf("%d\n",res); if(kase > 0) printf("\n"); } return 0;}
几乎全手写的代码,然而速度似乎更慢一些(120ms)
// Created by wander on 16/6/2.// Copyright © 2016年 W4anD0eR96. All rights reserved.// UVa 1151 Buy or Build// 类型:图论-生成树#include "bits/stdc++.h"using namespace std;int kase, n, q, es, res, p[1050], id[1050];int u[500050], v[500050], w[500050], r[500050];bool f(int i, int j) { return w[i] < w[j]; }pair<int, int> pos[1050];struct SubNet { int c, n, no[1050]; }sub[15];int Dist(pair<int, int>& a, pair<int, int>& b) { return (a.first - b.first) * (a.first - b.first) + (a.second - b.second) * (a.second - b.second);}int Find(int x) { return (p[x] != x) ? (p[x] = Find(p[x])) : x; }int main(){#ifdef DEBUG freopen("in", "r", stdin); freopen("out", "w", stdout);#endif scanf("%d", &kase); while (kase--) { scanf("%d%d", &n, &q); for (int i = 0 ; i < q ; i += 1){ scanf("%d%d",&sub[i].n, &sub[i].c); for (int j = 0 ; j < sub[i].n ; j += 1) scanf("%d", &sub[i].no[j]); } es = 0; for (int i = 1 ; i <= n ; i += 1) { scanf("%d%d",&pos[i].first, &pos[i].second); for (int j = 1 ; j < i ; j += 1) { u[es] = j; v[es] = i; w[es] = Dist(pos[i], pos[j]); es += 1; } } res = 0; for (int i = 0; i <= n; i += 1) p[i] = i; for (int i = 0; i < es; i += 1) r[i] = i; sort(r, r + es, f); for (int i = 0, cnt = 0; cnt < n - 1; i += 1) { int e = r[i], x = Find(u[e]), y = Find(v[e]); if (x != y) { res += w[e]; p[x] = y; id[cnt] = e; cnt += 1; } } for (int state = 1; state < (1 << q) ; state += 1) { int cnt = 0, t = 0; for (int i = 0 ; i <= n; i += 1) p[i] = i; for (int i = 0 ; i < q; i += 1) if ((state >> i) & 1) { t += sub[i].c; for (int k = 1 ; k < sub[i].n ; k += 1) { int x = Find(sub[i].no[k]), y = Find(sub[i].no[k - 1]); if (x != y) { p[x] = y; cnt += 1; } } } for (int i = 0; cnt < n - 1; i += 1) { int x = Find(u[id[i]]), y = Find(v[id[i]]); if (x != y) { t += w[id[i]]; p[x] = y; cnt += 1; } } res = min(res, t); } printf("%d\n",res); if (kase) putchar('\n'); } return 0;}
0 0
- uva 1151 Buy or Build
- UVA 1151 Buy or Build
- UVa 1151 Buy or Build
- UVA 1151 Buy or Build
- UVa 1151 Buy or Build
- uva 1151 Buy or Build
- Buy or Build UVA
- Buy or Build UVA
- UVA 1151Buy or Build MST
- (Uva)Buy or Build(B)
- uva 1151 - Buy or Build poj 2784 Buy or Build(最小生成树)
- 1151 - Buy or Build
- UVa #1151 Buy or Build (例题11-3)
- uva 1151 Buy or Build (最小生成树)
- UVA 1151 Buy or Build(生成树+二进制枚举)
- UVa 1151 Buy or Build (最小生成树)
- uva 1151 Buy or Build 状压枚举
- UVa 1151 Buy or Build--最小生成树+二进制选择
- 鼠标经过table表里行时改行的背景…
- CSS 实现 LI 鼠标…
- php中去除文字内容中所有html代码
- SecureCRT中文乱码解决方法(linux…
- MySQL错误信息:-bash:mysql:comma…
- UVa 1151 Buy or Build
- linux 如何登录mysql
- 鼠标经过table表里行时改行的背景…
- Linux下修改Mysql的用户(root)的密…
- Linux一键安装web环境全攻略phpstu…
- 错误:-bash: phpstudy:&nbsp…
- 用php+ajax写的仿百度谷歌搜索下拉…
- 64位Win7系统iTunes无法识别iPhone的解决方法
- 哪些工作需要做