题目链接:Problem 1963 交通建设
思路:多建一个虚拟的点,如果有机场,就和这个点相连,然后就是最小生成树问题了,最后要注意如果一开始没有机场,并且最后只有一条边和虚拟点相连,是需要扣掉权值CA的。
代码:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 1005; const int M = 12005; __int64 n, m, ca, cb, p, q, ans, pi, qi, parent[N], i, vis[N], flag; struct Edge { __int64 u, v, value; void scan() { scanf("%I64d%I64d%I64d", &u, &v, &value); value *= cb; } Edge() {} Edge(__int64 _u, __int64 _v, __int64 _value) { u = _u; v = _v; value = _value; } } e[M]; __int64 find(__int64 x) { if (x == parent[x]) return x; else return parent[x] = find(parent[x]); } bool Union(__int64 u, __int64 v) { int pa = find(u); int pb = find(v); if (pa != pb) { vis[u]++; vis[v]++; parent[pa] = pb; return true; } return false; } bool cmp(Edge a, Edge b) { return a.value < b.value; } __int64 solve() { sort(e, e + m + n + 1, cmp); for (i = 1; i <= m + n; i++) { if (Union(e[i].u, e[i].v)) ans += e[i].value; } if (vis[n + 1] == 1 && !flag) ans -= ca; return ans; } int main() { while (~scanf("%I64d%I64d%I64d%I64d", &n, &m, &ca, &cb)) { memset(vis, 0, sizeof(vis)); ans = 0; flag = 0; for (i = 1; i <= n + 1; i++) parent[i] = i; for (i = 1; i <= m; i++) e[i].scan(); for (i = m + 1; i <= m + n; i++) e[i] = Edge(i - m, n + 1, ca); scanf("%I64d", &p); ans += p * ca; while (p--) { flag = 1; scanf("%I64d", &pi); Union(pi, n + 1); } scanf("%I64d", &q); while (q--) { scanf("%I64d", &qi); ans += e[qi].value; Union(e[qi].u, e[qi].v); } printf("%I64d\n", solve()); } return 0; }
fzu 1963 交通建设(最小生成树),布布扣,bubuko.com
原文:http://blog.csdn.net/accelerator_/article/details/22514923