#include<stdio.h>
#include<string.h>
#include<stdlib.h>
const int Maxn=30010,Maxm=120010,Inf=1000000000;
int e,to[Maxm],ws[Maxm],begin[Maxn],next[Maxm];
int d[Maxn],p[Maxn],q[Maxn],pos[Maxn];
void add(int x,int y,int z){
to[++e]=y;
next[e]=begin[x];
begin[x]=e;
ws[e]=z;
}
int main(){
freopen("prim.in","r",stdin);
freopen("prim.out","w",stdout);
int i,j,k,m,n,l;
int x,y,z,u,v,w;
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
add(y,x,z);
}
for(i=1;i<=n;i++)d[i]=Inf;
d[1]=0;l=n;
for(i=1;i<=n;i++){q[i]=i;pos[i]=i;}
int ans=0;
for(i=1;i<=n;i++){
k=q[1];
q[1]=q[l];pos[q[l]]=1;l--;
u=1;
while( (u*2<=l && d[q[u]]>d[q[2*u]]) || (u*2+1<=l && d[q[u]]>d[q[2*u+1]]) ){
v=u*2;
if(v+1<=l && d[q[v]]>d[q[v+1]])v++;
w=q[u];q[u]=q[v];q[v]=w;
w=pos[q[u]];pos[q[u]]=pos[q[v]];pos[q[v]]=w;
u=v;
}
p[k]=1;
ans+=d[k];
for(j=begin[k];j;j=next[j]){
u=to[j];
if(!p[u] && d[u]>ws[j])d[u]=ws[j];
v=pos[u];
while(v>=1 && d[q[v]]<d[q[v/2]]){
w=q[v];q[v]=q[v/2];q[v/2]=w;
w=pos[q[v]];pos[q[v]]=pos[q[v/2]];pos[q[v/2]]=w;
v=v/2;
}
}
}
printf("%d\n",ans);
return 0;
}
最小生成树之PRIM-O(nlog2n)
最新推荐文章于 2021-07-19 15:04:41 发布