最小生成树直接用kruskal就好了
#include<bits/stdc++.h>
#define sf scanf
#define scf(x) scanf("%d",&x)
#define scff(x,y) scanf("%d%d",&x,&y)
#define scfff(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define vi vector<long long>
#define mp make_pair
#define pf prlong longf
#define prf(x) printf("%d
",x)
#define mm(x,b) memset((x),(b),sizeof(x))
#define rep(i,a,n) for (long long i=a;i<n;i++)
#define per(i,a,n) for (long long i=a;i>=n;i--)
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
const double eps=1e-6;
const double pi=acos(-1.0);
const long long inf=0x7fffffff;
const long long N=1e5+7;
struct Edge {
long long u, v, w; //边的顶点、权值
} edge[N*5]; //边的数组
long long pre[N]; //pre[i]为顶点 i 所在集合对应的树中的根结点
long long n, m; //顶点个数、边的个数
long long Find( long long x )
{ //查找并返回节点 x 所属集合的根结点
return pre[x]==x?x:pre[x]=Find(pre[x]);
}
bool cmp( Edge a, Edge b ) //实现从小到大排序的比较函数
{
return a.w < b.w;
}
long long Kruskal( )
{
for(int i=1;i<N;i++)pre[i]=i;
sort(edge,edge+m,cmp);
long long ans = 0; //生成树的权值
long long num = 0; //已选用的边的数目
long long u, v; //选用边的两个顶点
for(int i=0;i<m&&num<n-1;i++)
{
long long t1=Find(edge[i].u),t2=Find(edge[i].v);
if( t1!=t2 )
{
//prlong longf( "%d %d %d
", u, v, edge[i].w );
ans += edge[i].w;
num++;
pre[t1]=t2;
//pre[Find(t1)]=Find(t2);
}
}
return ans;
}
int main( )
{
long long u, v, w; //边的起点和终点及权值
scff(n,m); //读入顶点个数 n
rep(i,0,m)
scfff(edge[i].u,edge[i].v,edge[i].w);
long long ans=Kruskal();
cout<<ans;
return 0;
}