Kingdoms 枚举+最小生成树
来源:互联网 发布:宿迁网络电视台 编辑:程序博客网 时间:2024/06/15 16:02
A kingdom has n cities numbered 1 to n, and some bidirectional roads connecting cities. The capital is always city 1.
After a war, all the roads of the kingdom are destroyed. The king wants to rebuild some of the roads to connect the cities, but unfortunately, the kingdom is running out of money. The total cost of rebuilding roads should not exceed K.
Given the list of m roads that can be rebuilt (other roads are severely damaged and cannot be rebuilt), the king decided to maximize the total population in the capital and all other cities that are connected (directly or indirectly) with the capital (we call it “accessible population”), can you help him?
Input
The first line of input contains a single integer T (T<=20), the number of test cases.
Each test case begins with three integers n(4<=n<=16), m(1<=m<=100) and K(1<=K<=100,000).
The second line contains n positive integers pi (1<=pi<=10,000), the population of each city.
Each of the following m lines contains three positive integers u, v, c (1<=u,v<=n, 1<=c<=1000), representing a destroyed road connecting city u and v, whose rebuilding cost is c.
Note that two cities can be directly connected by more than one road, but a road cannot directly connect a city and itself.
Output
For each test case, print the maximal accessible population.
Sample Input
2
4 6 6
500 400 300 200
1 2 4
1 3 3
1 4 2
4 3 5
2 4 6
3 2 7
4 6 5
500 400 300 200
1 2 4
1 3 3
1 4 2
4 3 5
2 4 6
3 2 7
Sample Output
1100
1000
题意:有n个城市和m条路,k块钱,每个城市有一个权值。国王居住在1号城市,现在问你如何选出一些边总费用不超过k,使得跟1号城市连接的所有城市权值最大
思路:数据量比较小,城市只有16个,所有我们可以用状态保存下16个城市所有的状态,1表示已经选入,0表示未选入。
这样状态总数也只有1<<16=65536 所以我们可以枚举所有的状态,然后用最小生成树求出连通这些为1的结点所需要的最小费用是否大于k,枚举完后在费用<=k的状态里面取权值最大的即可。 注意1号城市一定会选入,这样状态可以少一维。
(转自http://blog.csdn.net/acm_cxq/article/details/52192026)
/* prim算法 AC:112ms*/#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <map>#include <vector>#define MM(s,q) memset(s,q,sizeof(s))#define INF 0x3f3f3f3f#define MAXN 1005#define Lchild id<<1#define Rchild (id<<1)+1#define FILE freopen("data.in","r",stdin)using namespace std;int popu[MAXN], mp[50][50], ans, vis[50], vis1[50];void prime(int status, int n, int KK) { int exist[20], cnt = 0, sum = 0; for (int i = 1; i <= n; i++) { if (status & (1 << (i - 1))) exist[cnt++] = i,sum+=popu[i]; } int dist[20]; MM(dist, INF); MM(vis,0); dist[1] = 0; int cost = 0; for (int i = 1; i <= cnt; i++) { int k = INF, pos; for (int j = 0; j < cnt; j++) { int a = exist[j]; if (!vis[a] && dist[a] < k) k = dist[a], pos = a; } vis[pos] = 1; cost += k; if (cost > KK) return; for (int j = 0; j < cnt; j++) { int a = exist[j]; if (!vis[a] && dist[a] > mp[pos][a]) dist[a] = mp[pos][a]; } } if (cost <= KK && sum > ans) ans = sum;}int main() { int T, n, m, k, u, v, w; cin >> T; while (T--) { MM(mp, INF); cin >> n >> m >> k; for (int i = 1; i <= n; i++) cin >> popu[i]; for (int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); mp[u][v] = mp[v][u] = min(w, mp[u][v]); } ans = 0; int status = 1 << n; for (int i = status - 1; i >= 1; i--) { if (!(i & 1)) continue; prime(i, n, k); } cout << ans << endl; }}
/* Kruskal 算法 AC:580ms */#include <iostream>#include <string>#include <cstring>#include <cstdio>#include <cmath>#include <cstdlib>#include <algorithm>#include <queue>#include <map>#include <vector>#define MM(s,q) memset(s,q,sizeof(s))#define INF 0x3f3f3f3f#define MAXN 1005#define Lchild id<<1#define Rchild (id<<1)+1#define FILE freopen("data.in","r",stdin)using namespace std;struct Edge { int u, v, w; Edge() {} Edge(int a, int b, int c) { u = a, v = b, w = c; } bool operator < (const Edge a)const { return w > a.w; }} tmp;int popu[MAXN], mp[50][50], F[MAXN], ans, vis[50][50], vis1[50];int Find(int x) { return F[x] == x ? x : (F[x] = Find(F[x]));}void Kruskal(int status, int n, int KK) { int k = 1, exist[20], cnt = 0, sum = 0; priority_queue<Edge> Q ; for (int i = 1; i <= n; i++) { if (status & (1 << (i - 1))) exist[cnt++] = i, sum += popu[i]; } for (int i = 0; i < cnt; i++) for (int j = 0; j < cnt; j++) { int a = exist[i], b = exist[j]; Q.push(Edge(a, b, mp[a][b])); } for (int i = 1; i <= n; i++)F[i] = i; int cost = 0; while (!Q.empty()) { tmp = Q.top(); Q.pop(); int u = tmp.u, v = tmp.v, w = tmp.w; int fa = Find(u), fb = Find(v); if (fa == fb) continue; F[fb] = fa; cost += w; if (cost > KK) return; } if (cost <= KK && sum > ans) ans = sum;}int main() { int T, n, m, k, u, v, w; cin >> T; while (T--) { MM(mp, INF); cin >> n >> m >> k; for (int i = 1; i <= n; i++) cin >> popu[i]; for (int i = 1; i <= m; i++) { scanf("%d%d%d", &u, &v, &w); mp[u][v] = mp[v][u] = min(w, mp[u][v]); } ans = 0; int status = 1 << n; for (int i = status - 1; i >= 1; i--) { if (!(i & 1)) continue; Kruskal(i, n, k); } cout << ans << endl; }}
- Kingdoms 枚举+最小生成树
- csu1116 Kingdoms 最小生成树-枚举状态
- 1116: Kingdoms+csuoj+暴力枚举+最小生成树
- csu 1116 Kingdoms 最小生成树 二进制枚举
- 湖南省第八届省赛 kingdoms (生成树+枚举)
- uva 12507 Kingdoms(dfs+最小生成树)
- LA3887 最小生成树 枚举最小边
- HDU 2489 DFS枚举+最小生成树
- hdu 2489(枚举 + 最小生成树)
- [BZOJ1050]HAOI2007旅行|最小生成树|枚举
- csu1116 最小生成树加枚举
- poj 3522 Slim Span(枚举+最小生成树)
- poj3522-kruscal算法求最小生成树+枚举
- hdu 2489 Minimal Ratio Tree(枚举+最小生成树)
- hdu 2489 Minimal Ratio Tree(dfs枚举 + 最小生成树)~~~
- 【UVALive】3887 Slim Span 枚举+最小生成树
- hud1598 find the mostcomfortable road最小生成树 暴力枚举
- 第八届省赛F题 (枚举+最小生成树)
- Android 设备WebView远程调试
- KVO 观察者模式
- java 自旋锁
- maven整合CXF WebService+Spring @Resource无法注入问题解决方法
- 点点滴滴——如何管理一个项目
- Kingdoms 枚举+最小生成树
- linux(预习六)
- 日志输出框架Log4j使用
- 彻底搞懂HashMap,HashTable,ConcurrentHashMap之关联
- Linux的一点复习
- 0417PHP
- Layer-list介绍与使用
- Uva-489 Hangman Judge
- 从存储结构理解php空,null,0'0'false