虽然标题我是这么写的,但是我也不确定并查集实现的最小生成树是不是克鲁斯卡尔算法,(还没学数据结构-。-)并查集实现最小生成树应用的是贪心的思想,之所以可行的原因是通过并查集可以实现节点联通后不再重复连接,所以贪心就可行了。
hdu 1863 畅通工程 (最小生成树)
http://acm.hdu.edu.cn/showproblem.php?pid=1863
// Problem: 畅通工程 // Contest: HDOJ // URL: http://acm.hdu.edu.cn/showproblem.php?pid=1863 // Memory Limit: 32 MB // Time Limit: 1000 ms // // Powered by CP Editor (https://cpeditor.org) #include <bits/stdc++.h> using namespace std; struct node { int start; int end; int cost; } road[105]; int f[105]; int find(int x) { int temp = x; while (x != f[x]) { x = f[x]; //把x变成x的老大 } if (x != f[temp]) f[temp] = x; return x; } void merge(int a, int b) { int la = find(a); int lb = find(b); if (la != lb) { f[la] = lb; } } int n, m; bool cmp(struct node a, struct node b) { return a.cost < b.cost; if (a.cost == b.cost) return a.start < b.start; } int main() { while (cin >> m >> n)//m是道路数,n是节点数 { if (m == 0) break; int count = 0; for (int i = 1; i <= n; i++) { f[i] = i; } for (int i = 1; i <= m; i++) { cin >> road[i].start; cin >> road[i].end; cin >> road[i].cost; } sort(road + 1, road + 1 + m, cmp); for (int i = 1; i <= m; i++) { if (find(road[i].start) != find(road[i].end)) { merge(road[i].start, road[i].end); count += road[i].cost; } } int cnt = 0; for (int i = 1; i <= n; i++) { if (f[i] == i) cnt++; } if (cnt == 1) printf("%d\n", count); else printf("?\n"); } }