标签:准则 畅通工程 cst min hdu 产生 div 没有 clu
题意:用路把各个村庄连起来,不一定要有直接的公路相连,只要能间接通过公路可达即可,给出每两个村庄之间的距离,求畅通需要的最少长度。
1.最小生成树 Kruskal 解法
先按长度从小到大排序,因为要求最短,那肯定要先把短的连起来,如果有一条边还没有连起来,并且这条边上的两个点在两个连通分量中,那就连接起来。
可以用第二组数据模拟一遍(排序后):
4
1 2 1
1 4 1
2 4 2
2 3 3
1 3 4
3 4 5
1 #include <cstdio> 2 #include <algorithm> 3 using namespace std; 4 5 const int maxn=111; 6 int Father[maxn]; 7 8 struct stt{ 9 int c1; 10 int c2; 11 int dis; 12 }T[5000]; 13 14 bool cmp(stt a,stt b){ 15 return a.dis<b.dis; 16 } 17 18 int find(int x){return x==Father[x]?x:Father[x]=find(Father[x]);} 19 20 void Union(int x,int y){ 21 int fx=find(x),fy=find(y); 22 if(fx!=fy){ 23 Father[fx]=fy; 24 } 25 } 26 27 int main(){ 28 int n; 29 while(scanf("%d",&n)!=EOF&&n!=0){ 30 31 for(int i=1;i<=n;i++){ 32 Father[i]=i; 33 } 34 35 int len=n*(n-1)/2; 36 37 for(int i=1;i<=len;i++){ 38 scanf("%d %d %d",&T[i].c1,&T[i].c2,&T[i].dis); 39 } 40 41 sort(T+1,T+len+1,cmp);//长度短的优先连接 42 int minlen=0; 43 44 for(int i=1;i<=len;i++){ 45 if(find(T[i].c1)!=find(T[i].c2)){//如果要连的那条边上的两个点在两个连通分量中,就把他们连接起来咯 46 minlen+=T[i].dis; 47 Union(T[i].c1,T[i].c2); 48 } 49 } 50 51 printf("%d\n",minlen); 52 } 53 return 0; 54 }
其实就是并查集问题,只不过用到最小生成树的思想。
思想步骤:
每一个步骤选择一条边加入生成树
贪心准则:不会产生环路,且耗费最小
可按照耗费递增顺序考察每条边:
(1)若产生环路,丢弃
(2)否则加入
HDU - 1233 还是畅通工程(带权并查集和最小生成树)
标签:准则 畅通工程 cst min hdu 产生 div 没有 clu
原文地址:http://www.cnblogs.com/Leonard-/p/6628418.html