HDU - 1233 还是畅通工程(Kruskal - MST)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1233
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 105 #define MAXM 10000 using namespace std; /**************************************************************************************************** 题意:给出城市中任意两个村庄的编号和距离,修一条公路使所有村庄联通,求最小的公路总长度 思路: 1,最小生成树算法,用 Kruskal算法 2,利用并查集维护每个联通集合 3,好好理解算法 PS:模板在邝斌的基础上做了修改,更加便于理解 ****************************************************************************************************/ int F[MAXN]; //并查集维护联通集合 struct Node{ int x,y,v; }node[MAXM]; bool cmp(Node x,Node y){ return x.v < y.v; } int Find(int x){ //找到每个点的父亲结点。(因为树的形状不重要,因此遍历之后将遍历过的结点改为树根的子结点) if(F[x] == -1) return x; else return F[x] = Find(F[x]); } int Kruskal(int n){ int tol = (n*(n-1))/2; //由点数确定边数 memset(F,-1,sizeof(F)); sort(node+1,node+tol+1,cmp); //将边排序后从小到大加入集合 int cnt = 0,ans = 0; for(int i = 1;i <= tol;i ++){ int t1 = Find(node[i].x),t2 = Find(node[i].y); if(t1 != t2){ ans += node[i].v; F[t1] = t2; cnt++; } if(cnt == n-1) break; } if(cnt < n-1) return -1; else return ans; } int main() { int n; while(cin>>n,n != 0){ int x,y,v; for(int i = 1;i <= (n*(n-1))/2;i ++) scanf("%d%d%d",&node[i].x,&node[i].y,&node[i].v); int ans = Kruskal(n); cout<<ans<<endl; } return 0; }