合训练的同学们~
解题思路:本题用的是Kruskal算法,我就是看着啊哈算法上的最小生成树(P212)来敲得代码,二者思路差不多,但我感觉那本书上对道路长度排序有些繁琐(就试着用sort排序直接将长度从小到大进行排序,结果也过啦,O(∩_∩)O哈哈~),畅通工程有好几道类似的题,大体思路都是一样的;
下边我来说一下本题使用到的具体算法吧:
首先按照边的权值进行从小到大排序,每次从剩余的边中选择权值较小且边的两个顶点不在同一个集合内的边(就是不会产生回路的边),加入到生成树中,直到加入n-1条边为止(n个村庄n-1条路即可使所有村庄连通)。
<span style="font-family:Times New Roman;font-size:18px;">#include<stdio.h> #include<algorithm> using namespace std; int n,m,pre[110]; struct road { int a,b,l; } s[5000]; bool cmp(road A,road B) { return A.l<B.l; //将道路长度按从小到大排序,为后面的选取最短边做准备 } int find(int i) { if(pre[i]==i) return i; return pre[i]=find(pre[i]); } int main() { int i,j,tx,ty; while(scanf("%d",&n)&&n) { m=n*(n-1)/2; for(i=1; i<=m; i++) scanf("%d%d%d",&s[i].a,&s[i].b,&s[i].l); sort(s,s+m+1,cmp); for(i=1; i<=n; i++) pre[i]=i; int count=0,sum=0; for(i=1; i<=m; i++) { tx=find(s[i].a); ty=find(s[i].b); if(tx!=ty) { pre[tx]=ty; count++; sum+=s[i].l; } if(count==n-1) break; } printf("%d\n",sum); } return 0; } </span>
