废话不说直接上板子
PS.打注释打了5分钟。。。。
#include<iostream>
#include<cstdio>
#define M 100
#define N 50
int d[N+1];
struct E {
int next,w,to;
} e[(M<<1)+1];
void adde(int a,int b,int w,int num) {
//详见http://blog.csdn.net/qq_21436421/article/details/53159093
e[num].next=d[a];
e[num].to=b;
e[num].w=w;
d[a]=num;
}
int father[N+1];
//并查集存点是否相连
int vis[N+1];
//代表已被染色的点
int zx(int num) {
if(num==father[num])return num;
else return father[num]=zx(father[num]);
}//并查集算祖先
void add(int a,int b) {
father[zx(a)]=father[zx(b)];
}//并查集合并两点
int main() {
int n,m;
scanf("%d%d",&n,&m);
int dt1,dt2,w;
for(int i=1; i<=m; ++i) {
scanf("%d%d%d",&dt1,&dt2,&w);
adde(dt1,dt2,w,(i<<1)-1);
adde(dt2,dt1,w,i<<1);
}
for(int i=1; i<=n; i++)father[i]=i;//并查集初始化
vis[1]=1;//初始化,染色点1(染哪个点都可以的。。。)
e[0].w=233333333;//初始化,由于mine初始值不好找,先设为0,方便更新
int ans=0;
for(int i=1; i<n; i++) {
int mine=0,minj;
for(int j=1; j<=i; j++)
//枚举已被染色的点
for(int k=d[vis[j]]; k; k=e[k].next)
//枚举:在 vis [j] 和 e[k].to 中连一条边
if( e[ k ]. w < e [ mine ]. w && zx( vis[ j ] ) != zx( e[k].to ) ) mine=k,minj=j;
//最终在vis[minj]和e[mine].to连边
ans+=e[mine].w;
e[mine].w=233333333;//将此边删去
add(vis[minj],e[mine].to);//合并这两点所在集合
vis[i+1]=e[mine].to;//染色这一个点
}
printf("%d",ans);
return 0;
}