CSU 1116 Kingdoms
原题链接:http://122.207.68.93/OnlineJudge/problem.php?id=1116
由于n比较小,直接枚举,然后对于每一个状态用最小生成树算法验证即可,感觉是水过去的,复杂度O(2n*n*m)。(有状压DP做法?)
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 20 struct Node { int u, v, w; }e[105]; int n, m, k, p[N], ans, f[N]; bool cmp(Node a, Node b) { return a.w < b.w; } int find(int x) { return f[x] == x ? x : (f[x] = find(f[x])); } bool ok(int cur) { int tot = 0; for(int i = 0; i < n; i++) f[i] = i; for(int i = 0; i < m; i++) { if(((cur>>e[i].u)&1) && ((cur>>e[i].v)&1)) { int x = find(e[i].u); int y = find(e[i].v); if(x != y) { if(x > y) f[x] = y; else f[y] = x; tot += e[i].w; } } } for(int i = 0; i < n; i++) // 所有要验证的点都必须和capital在同一个连通分量里面 if((cur>>i)&1 && find(i) != 0) return false; return tot <= k; } int main() { int t; scanf("%d", &t); while(t--) { scanf("%d%d%d", &n, &m, &k); for(int i = 0; i < n; i++) scanf("%d", &p[i]); Node tmp; for(int i = 0; i < m; i++) { scanf("%d%d%d", &tmp.u, &tmp.v, &tmp.w); tmp.u--; tmp.v--; e[i] = tmp; } sort(e, e+m, cmp); ans = -1; for(int i = 1; i < (1 << n); i++) { if(ok(i)) { int tot = 0; for(int j = 0; j < n; j++) { if((i >> j) & 1) tot += p[j]; } ans = max(ans, tot); } } printf("%d\n", ans); } return 0; }