最小生成树——kruscal算法,使用加权union-find并查集(路径压缩版)数据结构
#include<iostream>
#include<algorithm>
#include<cstdio>
#define NNUM 10005
#define PNUM 100005
using namespace std;
int node[NNUM]={0};
int connect[NNUM]={0},sz[NNUM]={0};
int N,P;
struct edge{
int x,y,d;
}e[PNUM];
int init(){
scanf("%d%d",&N,&P);
for(int i=0;i<N;i++){
cin>>node[i];
}
for(int i=0;i<P;i++){
scanf("%d%d%d",&e[i].x, &e[i].y,&e[i].d);
e[i].d=e[i].d*2+( node[e[i].x-1] + node[e[i].y-1]);
}
for(int i=0;i<N;i++){
connect[i]=i;
}
}
int cmp(edge e1,edge e2){
return e1.d<e2.d;
}
int find(int x){
return connect[x]==x ? x : connect[x]=find(connect[x]);
}
int kruscal(){
int ans=0;
sort(e,e+P,cmp);
for(int i = 0; i < P; i++){
int xx=find(e[i].x);
int yy=find(e[i].y);
if(xx==yy) continue;
//xx!=yy 则加入树里,ans增加该点权重
if(sz[xx]<sz[yy]){
connect[xx]=yy;
sz[yy]+=sz[xx];
}
else{
connect[yy]=xx;
sz[xx]+=sz[yy];
}
ans+=e[i].d;
}
return ans;
}
int main(){
init();
int min = 1<<30;
for(int i = 0; i < N; i++){
if(node[i] < min) min = node[i];
}
//别忘加起点 min
printf("%d\n", min+kruscal());
return 0;
}
Kruskal算法与加权并查集
1万+

被折叠的 条评论
为什么被折叠?



