最小生成树求连通图中经过所有点的最短路径
思路:将所有边有小到大排序 从小到大连接 连接前判断连接后会不会出现环 如果出现环就跳过 否则就连接 直到连接n-1条边
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int maxn=1010,maxm=10010;
struct node{
int x,y,w;
};
struct node a[maxm],tmp;
int f[maxn],rank[maxn];
void qsort(int l,int r){//快排 可以直接用sort
int mid=a[(l+r)/2].w,i,j;
i=l;
j=r;
while(i<j){
while(i<=j && a[i].w<mid)i++;
while(i<=j && a[j].w>mid)j--;
if(i<=j){
tmp=a[i];
a[i]=a[j];
a[j]=tmp;
i++;
j--;
}
}
if(l<j)qsort(l,j);
if(i<r)qsort(i,r);
}
int fa(int u){
if(f[u]!=u) //路径压缩
f[u]=fa(f[u]);
return f[u];
}
int find(int u,int v){
return fa(u)==fa(v)?0:1;
}
void link(int u,int v){
if(rank[fa(u)]>=rank[fa(v)]){ //启发式搜索
f[fa(v)]=fa(u);
rank[fa(u)]++;
}else{
f[fa(u)]=fa(v);
rank[fa(v)]++;
}
}
int main(){
int i,j,k,m,n,s;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)f[i]=i; //并查集
for(i=1;i<=m;i++)
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].w);
qsort(1,m);
s=n-1;i=0;
int ans=0;
while(s && i<=m){
i++;
if(find(a[i].x,a[i].y)){
link(a[i].x,a[i].y);
s--;
ans+=a[i].w;
}
}
printf("%d\n",ans);
return 0;
}