最小生成树kruskal求法这里不多赘述,就是对边权排序之后,用并查集去连接集合,知道剩下一个集合结束。

那么我们知道,如果要生成最小生成树唯一?为什么不唯一?就是因为存在连接两个集合中存在多种边权相同的方法。

那么我们直接把这些边权相同的但是连接相同的两个集合的一些边,留下一条,其余删掉就是最终答案了。

#include<bits/stdc++.h>
using namespace std;
typedef long long int;
const int INF=0x3f3f3f3f;
const int N=2e5+10;
struct edge{
	int a,b,w;
}e[N];
int n,m;
bool cmp(edge a,edge b){
	return a.w<b.w;
}
int p[N];
int find_set(int x){
	if(x!=p[x]) {
		p[x]=find_set(p[x]);
	}
	return p[x];
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		cin>>e[i].a>>e[i].b>>e[i].w;
	}
	for(int i=1;i<=n;i++)p[i]=i;
	sort(e+1,e+1+m,cmp);
	int ans=0;
	for(int i=1;i<=m;){	
		int j;
		for(j=i;j<=m;j++){
			if(e[i].w==e[j].w){
				if(find_set(e[j].a)!=find_set(e[j].b))
					ans+=e[i].w;
			}
			else
				break;
		}
		for(;i<j;i++){
			int x=find_set(e[i].a),y=find_set(e[i].b);
			if(x!=y){
				p[x]=y;
				ans-=e[i].w;
			}
		}
	}
	cout<<ans<<endl;
	return 0;
}