算法 最小生成树之 kruskal算法+并查集

本文介绍Kruskal算法结合并查集解决最小生成树问题的具体实现过程。通过初始化并查集、定义边结构体及比较函数,实现排序后的边依次尝试加入生成树,避免形成环路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法 最小生成树之 kruskal算法+并查集

kruskal算法需要从不同连通分量中选择连结边权最小的加入到生成树中,

每个连通分量可以看成一个等价类,初始每个顶点都是一个连通分量,将新边加入类似等价类的合并过程,

因此结合并查集算法实现kruskal

int father[N];
int rank[N];


void initset(int n)
{
     for(int i=1;i<=n;i++)
     {
             father[i]=i;// 用自身作集合值 
             rank[i]=0;// 秩初始值相同即可 
     }
}
typedef struct edge
{
        int a;
        int b;
        int dis;        
}edge;
const int M=10001;
edge e[M];// 边的数目是M 
bool cmp(const edge &a,const edge &b)
{
     return a.dis<b.dis;
}
// 带路径压缩 
int findset(int x)
{
    if(x!=father[x])
                    father[x]=findset(father[x]);
    return father[x];// 返回的是根集合 
    
}

void func1()
{
     int n,m;
    // while(cin>>n>>m)
    while(~scanf("%d%d",&n,&m))
     {     
         
       for(int i=0;i<m;i++)
       {
//               cin>>e[i].a>>e[i].b>>e[i].dis;
                 scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].dis);
       }  
       sort(e,e+m,cmp);
        int count=0;
        int sum=0;
       initset(n);  
       for(int i=0;i<m;i++)
       {
               int a=e[i].a;
               int b=e[i].b;
               int dis=e[i].dis;       
               int fa=findset(a);
               int fb=findset(b);
               if(fa!=fb)
               {
                 count++;
                 sum+=dis;
                 // rank merge按秩合并 ,注意合并的是fa,fb即根结点的集合值 
                 if(rank[fa]<rank[fb])
                 {
                     father[fa]=fb;
                 }else
                 {
                      father[fb]=fa;
                      if(rank[fa]==rank[fb])
                      {
                        rank[fa]++;
                      }
                 }
               }              
       }
       
       if(count<n-1)
       //cout<<"no"<<endl;
       printf("no\n");
       else
       //cout<<sum<<endl;
       printf("%d\n",sum);
     }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值