最小生成树

/*
最小生成树:如果一个连通无向图不包含回路,那么就是一个树。最小生成树就是求权值最小的这棵树
思路:首先选择权值最小的边,然后选择次短的,直至选择了n-1条边为止。选边时,需要判断两个顶点是否已连通,已连通就不选。
比较难实现的是判断两个顶点是否连通,可以使用深搜或广搜,但是这样效率低。更好的选择是使用并查集:将所有顶点放入一个并查集,判断两个顶点是否在同一集合。
这种方法叫Kruskal算法。
测试示例:
6 9
2 4 11
3 5 13
4 6 3
5 6 4
2 3 6
4 5 7
1 2 1
3 4 9
1 3 2
*/

#include <stdio.h>
#include <algorithm>
#include <iostream>
typedef struct{
    int u;
    int v;
    int w;
}Edge;//创建结构体用来存储边的关系
Edge e[1005];
int n,m;
int f[1005]={0},sum=0,count=0;//并查集用到的变量

bool cmp(Edge a,Edge b){
    return a.w<b.w;
}

//并查集寻找祖先的函数
int getf(int u){
    if(f[u]==u) return u;
    //路径压缩
    f[u]=getf(f[u]);
    return f[u];
}
//并查集合并两子集合的函数
int merge(int u,int v){
    int t1=getf(u);
    int t2=getf(v);
    if(t1!=t2){
        f[t2]=t1;
        return 1;
    }
    return 0;
}

int main()
{
    int i;
    //n表示顶点个数,m表示边的条数
    scanf("%d%d",&n,&m);
    //读入边
    for(i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    //按照权值从小到大对边进行快速排序
    //quicksort(1,m);
    std::sort(e+1,e+m+1,cmp);
    //并查集初始化
    for(int i=1;i<=m;i++)
        f[i]=i;
    //Kruskal算法核心部分
    for(i=1;i<=m;i++){//开始从小到大枚举每一条边
        //判断一条边的两个定点是否已经连通,即判断是否已经在同一个集合中
        if(merge(e[i].u,e[i].v)){
            count++;
            sum+=e[i].w;
        }
        if(count==n-1)//直到选到了n-1条边之后退出循环
            break;
    }
    printf("%d\n",sum);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值