刚开始写时用的是一般的Kruskal算法,结果是超时,后来改为Kruskal+优先队列,结果是出错了,因为不太了解STL的知识,很难下手找出问题,所以上网找了别人的代码看了一下,然后学习了一下heap堆,就写出来了。发现STL真的好强大啊
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
const int maxn=1002;
int bin[maxn],rank[maxn];
double x[maxn],y[maxn];
struct Edge
{
int u;
int v;
double w;
bool operator<(const Edge &a)const
{
return w>a.w;
}
}edge[maxn*maxn];
double dist(double x1,double y1,double x2,double y2)
{
return sqrt(pow(x2-x1,2)+pow(y2-y1,2));
}
int find(int x)
{
int i,j,r;
r=x;
while(r!=bin[r])
r=bin[r];
i=x;
while(i!=r)
{
j=bin[i];
bin[i]=r;
i=j;
}
return r;
}
bool merge(int a,int b)
{
int u,v;
u=find(a);
v=find(b);
if(u!=v)
{
if(rank[u]==rank[v])
{
rank[u]++;
bin[v]=u;
}
else if(rank[u]>rank[v])
bin[v]=u;
else
bin[u]=v;
return true;
}
else
return false;
}
int main()
{
int i,j,n,m,a,b,num,cnt;
double sum;
while(scanf("%d%d",&n,&m)!=EOF)
{
for(i=1;i<=n;i++)
{
bin[i]=i;
rank[i]=0;
}
for(i=1;i<=n;i++)
scanf("%lf%lf",&x[i],&y[i]);
num=0;
for(i=1;i<n;i++)
for(j=i+1;j<=n;j++)
{
edge[num].u=i;
edge[num].v=j;
edge[num++].w=dist(x[i],y[i],x[j],y[j]);
}
make_heap(edge,edge+num); //建立小根堆,权值越小的优先级越高
cnt=1;
for(i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
if(merge(a,b)) //两个结点不在同一个树上
cnt++;
}
for(i=0;i<num && cnt<n;i++)
{
if(merge(edge[0].u,edge[0].v))
{
cnt++;
sum+=edge[0].w;
}
pop_heap(edge,edge+num);
num--;
}
printf("%.2lf\n",sum);
}
return 0;
}