图的最小生成树 (Kruskal算法)

这里写图片描述
这里写图片描述

#include <stdio.h>

struct edge
{
    int u;
    int v;
    int w;
};

int f[7],sum=0,cnt=0,n,m;//f数组大小根据n的值决定;
struct edge t,e[10];//e数组的值由m的值决定。


//快速排序
void quicksort(int left,int right)
{
    int i,j;
    if(left>right)
        return;
    i=left,j=right;
    int temp=e[left].w;
    while(i!=j)
    {
        while(e[j].w>=temp&&i<j)
            j--;
        while(e[i].w<=temp&&i<j)
            i++;
        if(i<j)
        {
            t=e[i],e[i]=e[j];e[j]=t;
        }
    }
    t=e[i],e[i]=e[left],e[left]=t;
    quicksort(left,i-1);
    quicksort(i+1,right);
    return;
}

void init()
{
    for(int i=1;i<=n;i++)
        f[i]=i;
    return;
}

//找爹,直到找到祖宗,擒贼先擒王。
int getf(int v)
{
    if(f[v]==v)
        return v;
    else
    {
        //路径压缩,每次函数返回的时候,把路上遇到的人的BOSS改为最后找到的祖宗编号。
        f[v]=getf(f[v]);
        return f[v];
    }
}

//合并两子集合的函数
int merge(int x,int y)
{
    int t1,t2;

    t1=getf(x);
    t2=getf(y);
    if(t1!=t2)
    {
        f[t2]=t1;   //靠左原则,左边变为右边的BOSS
        return 1;
    }
    return 0;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
    quicksort(1,m);
    init();
    //Kruskal算法核心
    for(int i=1;i<m;i++)//开始从小到大枚举每一条边。
    {
        //判断一条边的两个顶点是否已经联通,即判断是否在一个集合中
        if(merge(e[i].u,e[i].v))//如果目前尚未不连通,则选用这条边。
        {
            cnt++;
            sum+=e[i].w;
        }
            if(cnt==n-1)//直到选用n-1条边后退出循环。
            break;
    }

    printf("%d\n",sum);
    return 0;
}
/*
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
*/
//#define debug

struct node{
    int u,v,w;
};

bool cmp(const node& a,const node& b){
    return a.w<b.w;
}

int fa[1005];

int get_father(int x){
    return fa[x]=fa[x]==x?x:get_father(fa[x]);
}

int main()
{
    #ifdef debug
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif // debug

    node mmp[15005];
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF){
        for(int i=0;i<m;i++){
            scanf("%d%d%d",&mmp[i].u,&mmp[i].v,&mmp[i].w);
        }
        sort(mmp,mmp+m,cmp);
        int ans=0;
        for(int i=1;i<=n;i++) fa[i]=i;
        int cnt=0;
        for(int i=0;i<m;i++){
            if(get_father(mmp[i].u)!=get_father(mmp[i].v)){
                ans+=mmp[i].w;
                fa[fa[mmp[i].u]]=fa[mmp[i].v];
                cnt++;
                if(cnt==n-1){
                    break;
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值