最小生成树之Kruska 洛谷P3366

/*
    最小生成树之Kruskal  洛谷P3366
    
    用于解决最小费用的连通图,整体最小。

    对所有节点遍历建立并查集,按照边的权重建立最小堆(升序排序)
    取出最小堆堆顶数据,并判断两端节点是否在同一集合
    如不在,则将这两个节点添加到同一集合,接着将边加入生成边,如在,则不进行操作,为无效边
    重复上面的操作,直到所有的边都检查完
*/
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 2e5+10;
int f[maxn]; // 记录边的关系

struct node{
    int u,v,w;
};
node nums[maxn];
bool cmp(node a,node b){
    return a.w<b.w;
}
int n,m;
// 查找
int Find(int x){
    if(x==f[x])
        return x;
    return f[x]=Find(f[x]);
}

// 合并边
void Union(int x,int y){
    f[Find(x)]=Find(y);
}

void Kruskal(){
    // 初始化
    for(int i=1;i<=n;i++)
        f[i]=i;
    // 排序
    sort(nums,nums+m,cmp);
    int ans = 0;// 边权值
    int G = 0;// 记录边
    for(int i=0;i<m;i++){
        int u = nums[i].u;
        int v = nums[i].v;
        if(Find(f[u])!=Find(f[v])){  // 判断是否相连
            Union(u,v); // 合并
            G++; // 边数+1
            ans += nums[i].w; // 权值 +
        }
    }
    if(G == n-1) 
        cout<<ans;
    else 
        cout<<"orz";
}

void Solve(){
    cin>>n>>m;
    int x,y,z;
    for(int i=0;i<m;i++){
        scanf("%lld %lld %lld",&x,&y,&z);
        nums[i]={x,y,z};
    }
    Kruskal();
}

signed main(){
    int t =1 ;
    //cin>>t;  // 用于多组数据
    while(t--){
        Solve();
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值