/*
最小生成树之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();
}
}
最小生成树之Kruska 洛谷P3366
于 2023-07-20 11:42:05 首次发布