题目
最小生成树。
思路
使用小根堆对prim算法进行优化。
参考第二十六天和第二十八天。
代码
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN=100000+1;
const int MAXM=1000000+1;
int N,M,vis[MAXN];
int head[MAXN],e=0;
int w[MAXM],top=1;
struct EDGE
{
int v,next,cost;
}edge[MAXM<<1];
void addEdge(int x,int y,int z)
{
edge[e].v=y;
edge[e].cost=z;
edge[e].next=head[x];
head[x]=e++;
}
void add(int p)
{
int i=top++;
while(i!=1 && edge[w[i>>1]].cost>edge[p].cost)
{
w[i]=w[i>>1];
i>>=1;
}
w[i]=p;
}
int out()
{
int ans=w[1];
int i=1;
w[1]=w[--top];
while((i=i<<1)<top)
{
i=((i|1)>=top || edge[w[i]].cost<edge[w[i|1]].cost)?i:i|1;
if(edge[w[i>>1]].cost>edge[w[i]].cost)
{
w[i>>1]=w[i];
w[i]=w[top];
}
else break;
}
return ans;
}
int prim()
{
int ans=0,k;
memset(vis,0,sizeof(vis));
vis[1]=1;
for(int i=head[1];i!=-1;i=edge[i].next) add(i);
for(int i=1;i<N;i++)
{
do{k=out();} while(vis[edge[k].v]);
vis[edge[k].v]=1; ans+=edge[k].cost;
for(int p=head[edge[k].v];p!=-1;p=edge[p].next) if(!vis[edge[p].v]) add(p);
}
return ans;
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&N,&M);
int a,b,c;
while(M--)
{
scanf("%d%d%d",&a,&b,&c);
addEdge(a,b,c);
addEdge(b,a,c);
}
printf("%d",prim());
return 0;
}