Kruskal poj 1287 示例 [ 实现用到并查集 ]
克鲁斯卡尔算法 (加边法)
G(V, E) 带权连通无向图
(1), 将 G 中的边按权值从小到大依次选取,若选取的边使生成树不构成回路,并入 TE 中。
(2), 从剩下的边中选取边,执行操作 (1), 如此进行下去,直到 TE 中包含 n-1 条边为止,此时的T,此时的 T ,即为最小生成树。
Kruskal 的实现需要用到并查集。
#include <iostream> #include <string> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <stack> #include <deque> #include <queue> #include <bitset> #include <list> #include <map> #include <set> #include <iterator> #include <algorithm> #include <functional> #include <utility> #include <sstream> #include <climits> #include <cassert> #define BUG puts("here!!!"); using namespace std; const int N = 5005; int pre[N]; int n, m; struct Node { int u, v; int w; }e[N]; bool cmp(const Node a, const Node b) { return a.w < b.w; } void makeSet(int n) { for(int i = 0; i <= n; i++) { pre[i] = i; } } int findSet(int a) { if(pre[a] == a) return a; return pre[a] = findSet(pre[a]); } void kruskal() { int fu, fv, sum = 0, count = 0; sort(e, e+m, cmp); makeSet(n); for(int i = 0; i < m; i++) { fu = findSet(e[i].u); fv = findSet(e[i].v); if(fu != fv) { sum += e[i].w; count++; if(count == n-1) break; pre[fv] = fu; } } cout << sum << endl; } int main() { while(cin >> n, n) { cin >> m; for(int i = 0; i < m; i++) { cin >> e[i].u >> e[i].v >> e[i].w; } kruskal(); } return 0; }