Kruskal算法

//最小生成树:Kruskal算法
#include <stdio.h>
#include <algorithm>
using namespace std;
#define arraysize 15001
#define nodenum 1001
typedef struct node
{
 int start;    //起点
 int end;    //终点
 int w;     //费用
};
node edges[arraysize];  //存储边
node record[arraysize];  //存储最小生成树中的边
int final[nodenum];   //存储该点的双亲节点
int r[nodenum];    //存储以nodenum为根的树的节点数(包括根)
bool cmp(node a,node b)

 return a.w<b.w;
}
int findroot(int n)   //找到n的根节点
{
 if(final[n] == n)
  return n;
 else
 {
  final[n] = findroot(final[n]);
 }
 return final[n];
}
int main()
{
 //freopen("1.txt","r",stdin);
 int N,M;
 while(scanf("%d%d",&N,&M)!=EOF)
 {
  int start,end,w;
  for(int i=1;i<M+1;++i)
  {
   scanf("%d%d%d",&start,&end,&w);
   edges[i].start = start;
   edges[i].end = end;
   edges[i].w = w;
  }
  //Kruskal算法,初始化,建立n棵树
  for(int i1=1;i1<N+1;i1++)
  {
   final[i1] = i1;
   r[i1] = 1;
  }
  //对边进行排序
  sort(edges+1,edges+M+1,cmp);  //此处第一个参数是edges+1,第二个参数是edges+M+1
  int flag = 0;      //记录最小生成树中的边数
  int maxLength = 0;     //记录最小生成树种的最大边
  //遍历所有的边
  for(int i2=1;i2<M+1;++i2)
  {
   int a = edges[i2].start;
   int b = edges[i2].end;
   int w = edges[i2].w;
   //查找边的源点的根节点
   int roota = findroot(a);
   //查找边的终点的根节点
   int rootb = findroot(b);
   //如果边的源点和边的终点不在同一连通子图中,则将该点加入到最小生成树中
   if(roota != rootb)
   {
    flag++;
    record[flag].start = a;
    record[flag].end = b;
    record[flag].w = w;
    if(record[flag].w>maxLength)
    {
     maxLength = record[flag].w;
    }
    if(r[roota]>=r[rootb])
    {
     final[rootb] = a;
     r[roota] += r[rootb];
    }
    else
    {
     final[roota] = b;
     r[rootb] += r[roota];
    }
   }
   if(flag == N-1)  //找到了最小生成树
   {
    printf("%d/n%d/n",maxLength,flag);
    for(int j=1;j<=flag;++j)
    {
     printf("%d %d/n",record[j].start,record[j].end);
    }
    break;
   }
  }
 }  
 return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值