题目链接:http://poj.org/problem?id=1797
开始题意理解错。不说题意了。
并不想做这个题,主要是想测试kruskal 模板和花式并查集的正确性。
已AC;
/* 最小生成树 kruskal算法 过程:每次选取没有参与构造最小生成树并且加入之后不会构成回路的边中权值最小的一条 作为最小生成树的一条新边。直至选择了V-1条边。 */ #include <stdio.h> #include <string.h> #include <iostream> #include <algorithm> #define maxn 2100 using namespace std; int fa[maxn], r[maxn]; void init(int n) { for (int i=1; i<=n; ++i) { fa[i] = i; r[i] = 1; } } int find_fa(int v) { // 递归式路径压缩 if (fa[v] != v) fa[v] = find_fa(fa[v]); return fa[v]; } /*int find_fa(int v) { // 非递归式路径压缩 int k, j, r; r = v; while(r != fa[r]) r = fa[r]; //找到根节点 记录在r上。 k = v; while(k != r) { j = fa[k]; fa[k] = r; k = j; } return r; }*/ /*void unin(int u, int v) { // 非按秩合并 int fau = find_fa(u); int fav = find_fa(v); if (fau != fav) fa[fav] = fau; }*/ void unin(int u, int v) { // 按秩合并 int fau = find_fa(u); int fav = find_fa(v); if (fau == fav) return; if (r[u] < r[v]) fa[fau] = fav; else { if (r[u] == r[v]) r[u]++; fa[fav] = fau; } } struct Edge { int u, v, w; }edge[1000010]; bool cmp(Edge a, Edge b) { return a.w > b.w; } int ans; int kruskal(int n, int m) { // 传入顶点个数n 和 边的个数m init(n); sort(edge, edge+m, cmp); ans = 0; int ret = 0; // 生成树的总权值 int cnt = 0; // 已加入最小生成树的边的数量 for (int i=0; i<m; ++i) { if (find_fa(1) == find_fa(n)) return -1; int u = edge[i].u; int v = edge[i].v; if (find_fa(u) != find_fa(v)) { cnt++; ret += edge[i].w; unin(u, v); ans = edge[i].w; } if (cnt == n-1) return ret; // 已找到n-1条边,生成树构造完毕 } return -1; } int main() { int casee = 1; int t; cin >> t; while(t--) { int n, m; cin >> n >> m; for (int i=0; i<m; ++i) { cin >> edge[i].u >> edge[i].v >> edge[i].w; } kruskal(n, m); cout << "Scenario #" << casee++ << ":" << endl << ans << endl << endl; } return 0; }