#include<bits/stdc++.h>
using namespace std;const int N=5e+3+10;//看准数据范围,(我第一次提交时,RU了4个点;数组开小了) const int M=2e+5+10;
int pre[N]={0};
struct st{
int v1,v2;//两个顶点
int w;//边权 st(){v1=v1=w=0;}//初始化(在这一题没什么用,但是定义时初始化是个好习惯噢!) }s[M];
int cmp(const st &a,const st &b){//sort的排序条件(比较权值决定传值的两个元素是否交换) return a.w<b.w;}
int find(int x){//找祖先
int t=x;while(pre[t]!=t)//只有祖先元素的值是自己(主函数里pre数组初始化每个数组元素都是自己的祖先) {
t=pre[t];//循环前往上一辈 }return t;//返回祖先 }
int main(){
int n,m;//n:结点数 m:边数
int sum=0;//最小代价计数
int k=0;//最小生成树加入边数计数(n-1)//都一条边就有环路,少一条就不连通
int x,y,w;
int t1,t2;
cin>>n>>m;for(int i=1;i<=n;i++)//初始化 {//每个元素都是自己的祖先
pre[i]=i;}for(int i=0;i<m;i++){//记录每条边的两个顶点和权值
cin>>x>>y>>w;
s[i].v1=x,s[i].v2=y;
s[i].w=w;}sort(s,s+m,cmp);//按权值从小到大排序 /*
从小到大排序后,循环时就可以优先选择边的权值小的边;
然后循环中就不用考虑这个边是否是可加入最小的边;
只需要判断加入这个边是否会形成环路;
*/for(int i=0;i<m;i++){
x=s[i].v1,y=s[i].v2;
w=s[i].w;
t1=find(x);//找祖先
t2=find(y);//找祖先 if(t1!=t2)//祖先不一样(生成树加入该边不会构成环路) {
k++;//生成树边数记录
sum+=w;//生成树权值累加
int f1,f2;
pre[y]=t1;//让y认x的祖先为y的祖先
pre[t2]=t1;//让y的祖先也认x的祖先为自己的祖先 /*
这就是压缩路径,使每个元素找到祖先(最上面的一级)的步骤减少;
但是这样就找不到爸爸(离自己最近的上一级);因为所有元素都在尽可能
认祖先为爸爸,原来的爸爸就找不到了; 不过不影响这一的运作过程;
*/if(k==n-1)//最小生成树形成,循环结束 break;}else//祖先一样,x,y属于一棵树(连通分支) continue;}
cout<<sum<<endl;return0;}
暴力广搜超时60%(O(n^3))
#include<bits/stdc++.h>
using namespace std;
typedef struct st ak;const int N=5e+3+10;const int M=2e+5+10;
int e[N][N]={0};//邻接矩阵
struct st{
int v1,v2,w;st(){v1=v2=w=0;}}s[M];
int n;
int m;//结点数
int cmp(ak a,ak b){return a.w<b.w;}
int find(int x,int y){//广搜从一个顶点出发//从x出发能够到达y,说明x,y在一个连通分量中,return 0;//否则 return 1;
int q[N]={0};
int f=0,r=0;
int book[N]={0};
q[r++]=x;
book[x]=1;while(f!=r){
int k=q[f++];for(int i=1;i<=m;i++){if(!book[i]&&e[k][i]!=0){
book[i]=1;if(i==y)return0;
q[r++]=i;}}}return1;}
int main(){
int sum=0;
int k=0;
cin>>m>>n;//m结点数,n边数 for(int i=0;i<n;i++){
int x,y,w;
cin>>x>>y>>w;
s[i].v1=x,s[i].v2=y,s[i].w=w;}sort(s,s+n,cmp);//按权值从小到大排序 for(int i=0;i<n;i++){
int x,y,w;
x=s[i].v1,y=s[i].v2,w=s[i].w;//printf("[%d,%d,%d]->\n",x,y,w);if(x==y)//自环 跳过 continue;if(find(x,y)==1)//判断x,y是否在一个联通分量中 {
e[x][y]=w;
e[y][x]=w;
sum+=w;}else//在一个连通分量中,重边,选择权值最小的,作为边权 {//新权值小于原有权值 //更新x->y和y->x的权值 if(w<e[x][y]){
sum-=e[x][y];
e[x][y]=e[y][x]=w;
sum+=w;}}}
cout<<sum<<endl;return0;}/*
5 8
1 3 4
1 2 1
1 4 5
2 5 2
2 4 4
3 5 3
4 5 2
3 5 1
*//*
5 18
2 4 276
3 3 435
3 4 608
2 4 860
1 2 318
1 3 547
5 4 419
2 5 98
1 5 460
5 3 399
3 5 240
3 2 733
3 3 903
4 2 909
5 2 206
3 4 810
2 1 115
2 3 419
*/