克鲁斯卡尔算法(Kruskal算法) 考研计算机

5 篇文章 0 订阅
3 篇文章 0 订阅

相比较克鲁斯卡尔来说,prime 和 迪杰斯特拉是以点展开验证边。而克鲁斯卡尔是以边为展开看连接点点是否属于都一个跟(并查集)

  #include <stdio.h>
  #include <string.h>
  #include <algorithm>
  #define MAXN 11  //顶点个数的最大值
  #define MAXM 20  //边的个数的最大值
  using namespace std; 
//测试样例
//7 12
//1 2 12
//1 6 16
//1 7 14
//2 6 7
//2 3 10
//3 6 6
//3 4 3
//3 5 5
//4 5 4
//5 6 2
//5 7 8
//6 7 9  
  struct edge  //边
  {
     int u, v, w; //边的顶点、权值
 }edges[MAXM]; //边的数组
 
 int parent[MAXN];  //parent[i]为顶点 i 所在集合对应的树中的根结点
 int n, m;  //顶点个数、边的个数
 int i, j;  //循环变量
 void UFset( )  //初始化
 {
     for( i=1; i<=n; i++ ) 
         parent[i] = -1;
 }
 int Find( int x ) //查找并返回节点 x 所属集合的根结点
 {
     int s; //查找位置
     for( s=x; parent[s]>=0; s=parent[s] );
     while( s!=x ) //优化方案―压缩路径,使后续的查找操作加速。
     {
         int tmp = parent[x];
         parent[x] = s;
         x = tmp;
     }
     return s;
 }
 
 //将两个不同集合的元素进行合并,使两个集合中任两个元素都连通
 void Union( int R1, int R2 )
 {
     int r1 = Find(R1), r2 = Find(R2); //r1 为 R1 的根结点,r2 为 R2 的根结点
     int tmp = parent[r1] + parent[r2]; //两个集合结点个数之和(负数)
     //如果 R2 所在树结点个数 > R1 所在树结点个数(注意 parent[r1]是负数)
     if( parent[r1] > parent[r2] ) //优化方案――加权法则
     {
         parent[r1] = r2; 
         parent[r2] = tmp;
     }
     else
     {
         parent[r2] = r1; 
         parent[r1] = tmp;
     }
 }
 bool cmp( edge a, edge b ) //实现从小到大排序的比较函数
 {
     return a.w <= b.w;
 }
 void Kruskal( )
 {
     int sumweight = 0;  //生成树的权值
     int num = 0;  //已选用的边的数目
     int u, v;  //选用边的两个顶点
     UFset( ); //初始化 parent[]数组
     for( i=0; i<m; i++ )
     {
         u = edges[i].u; v = edges[i].v;
         if( Find(u) != Find(v) )
         {
             printf( "%d %d %d\n", u, v, edges[i].w );
             sumweight += edges[i].w; num++;
             Union( u, v );
         }
         if( num>=n-1 ) break;
     }
     printf( "weight of MST is %d\n", sumweight );
 }
 int main( )
 {
     int u, v, w; //边的起点和终点及权值
     scanf( "%d%d", &n, &m ); //读入顶点个数 n
     for( int i=0; i<m; i++ )
     {
     scanf( "%d%d%d", &u, &v, &w ); //读入边的起点和终点
     edges[i].u = u; edges[i].v = v; edges[i].w = w;
     }
     printf("\n");
     sort(edges,edges+m,cmp);
     Kruskal();
     return 0;
 }

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值