浙大 2006 还是畅通工程(最小生成树,Kruskal算法)

题目:
给出编号为1,2,......,N的N(N<100)个点两两间的距离,求该图的最小生成树的边和。

思路:
求最小生成树,用Kruskal算法。

知识点回顾:
1.Kruskal算法:初始时所有点孤立,属于不同的点集。
               把边按权值从小到大排序,然后遍历边。
               若边的两点属于不同点集,则该边为最小生成树的一部分,并把两点所在集合合并。
               遍历完所有边,若所有点在同一点集,则找到最小生成树;否则原图不连通,没有最小生成树。

过程:
这次调试用了很久很久,出错的地方竟然在不起眼的cmp()函数上,即如果要从小到大排,要用“<”,不要用“<=”(从大到小同理),具体原因还未知(问题只出在九度OJ上,自己的编译器没问题)。

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <algorithm>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 //并查集
 8 int tree[102];              //存点的父结点(根节点的值为0)
 9 int findRoot(int i){        //返回点所在父结点,并压缩树
10     int j=i,k=i,t;
11     while(tree[j]!=0){            //找到i结点的根结点j
12         j=tree[j];
13     }
14     while(tree[k]!=0){            //压缩树
15         t=k;
16         k=tree[k];
17         tree[t]=j;
18     }
19     return j;
20 }
21 
22 //
23 struct Edge{
24     int a;         //a->b
25     int b;
26     int value;     //边的权值
27 };
28 
29 Edge edge[5000];   //存边
30 
31 //边比较函数
32 bool cmp(Edge e1,Edge e2){
33     if(e1.value<e2.value)
34         return true;
35     return false;
36 }
37 
38 //主函数
39 int main(){
40     int N,i,j,sum;
41     int a,b,value,r1,r2;
42     while(scanf("%d",&N)!=EOF && N){                            //输入点数
43         memset(tree,0,102*sizeof(int));                               //把点各自分为独立集合
44         sum=0;
45         j=N*(N-1)/2;                                                  //计算边数
46         for(i=0;i<j;i++){                                             //循环输入边
47             scanf("%d %d %d",&edge[i].a,&edge[i].b,&edge[i].value);
48         }
49         sort(edge,edge+j,cmp);                                        //把边按权值从小到大排序
50         for(i=0;i<j;i++){                                             //遍历边
51             a=edge[i].a;  b=edge[i].b;  value=edge[i].value;                //边的信息
52             r1=findRoot(a); r2=findRoot(b);                                 //找到根
53             if(r1!=r2){                                                        //两点不在同集合,则该边为最小生成树的一部分                                                          
54                 sum+=value;                                                          //把该边的权值加入和
55                 tree[r1]=r2;                                                      //合并两集合
56             }
57         }
58         printf("%d\n",sum);
59     }
60     return 0;
61 }

 

转载于:https://www.cnblogs.com/songshu-gancuimian/p/6805956.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值