刚开始做这题时,用的是Kruskal算法做的,做了很长时间没有做出来,后来发现是结构体里的距离len不能定义为double类型的(double类型的数据在计算时很不稳定),就改成Int类型的,改完后还是WA,看了很久后也没有找出来,无奈之下上网看了看别人的解题报告,核心算法还是一样,不同之处在于合并时出问题了。
下面贴出用Kruskal和Prim算法AC了的,和用Kruskal算法WA的代码……
//WA
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn1=502;
const int maxn2=125000;
bool visit[maxn1];
int num,bin[maxn1];
double sum;
struct node
{
int x;
int y;
int tag;
}point[maxn1];
struct Edge
{
int id1;
int id2;
int tag; //标记是否参与构成最小生成树,0表示没有,1表示参与了
int len;
}edge[maxn2];
bool cmp(Edge a,Edge b)
{
return a.len<b.len;
}
int length(node p1,node p2)
{
return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
}
int find(int x)
{
int r;
r=x;
while(r!=bin[r])
r=bin[r];
return r;
}
void Kruskal()
{
int i,j,u,v,a,b;
for(i=0;i<num;i++)
{
u=edge[i].id1;
v=edge[i].id2;
if(!visit[u] && !visit[v])
{
a=find(u);
b=find(v);
bin[a]=b;
visit[u]=true;
visit[v]=true;
}
else if(!visit[u] && visit[v])
{
a=find(u);
b=find(v);
bin[a]=b;
visit[u]=true;
}
else if(visit[u] && !visit[v])
{
a=find(u);
b=find(v);
bin[b]=a;
visit[v]=true;
}
else
{
a=find(u);
b=find(v);
if(a==b)
continue;
bin[a]=b;
}
edge[i].tag=1; //这条边参与构成最小生成树
}
}
int main()
{
int i,j,t,s,p;
double d;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&s,&p);
for(i=0;i<p;i++) //点的个数为p,从零开始标号
{
scanf("%d%d",&point[i].x,&point[i].y);
point[i].tag=0;
}
if(s==p)
continue;
num=0;
for(i=0;i<p-1;i++)
for(j=i+1;j<p;j++)
{
edge[num].id1=i;
edge[num].id2=j;
edge[num].tag=0;
edge[num++].len=length(point[i],point[j]);
}
for(i=0;i<=p;i++)
bin[i]=i;
sort(edge,edge+num,cmp);
memset(visit,0,sizeof(visit));
Kruskal();
for(i=num-1;i>=0;i--)
if(edge[i].tag==1)
{
d=edge[i].len;
if(s==0)
break;
if(!point[edge[i].id1].tag)
{
point[edge[i].id1].tag=1;;
s--;
}
if(s==0)
break;
if(!point[edge[i].id2].tag)
{
point[edge[i].id2].tag=1;
s--;
}
}
printf("%.2lf\n",sqrt(d));
}
return 0;
}
--------------------------------------------------------------------------------------
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int maxn=502;
int x[maxn],y[maxn],bin[maxn],r[maxn];
int num,s,p;
struct Edge
{
int u;
int v;
int len;
}edge[maxn*maxn];
int cmp(const void *a,const void *b)
{
Edge *p=(Edge *)a,*q=(Edge *)b;
return p->len-q->len;
}
int dist(int x1,int y1,int x2,int y2)
{
return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
int find(int x)
{
int r;
r=x;
while(r!=bin[r])
r=bin[r];
return r;
}
int Kruskal()
{
int i,u,v,n,m;
n=0;
m=p-s;
for(i=0;i<num;i++)
{
u=find(edge[i].u);
v=find(edge[i].v);
if(u!=v)
{
if(r[u]>=r[v])
{
bin[v]=u;
if(r[u]==r[v])
r[u]++; //连通分支数加1
}
else
bin[u]=v;
n++;
if(n>=m)
break;
}
}
return edge[i].len;
}
int main()
{
int i,j,t;
double d;
scanf("%d",&t);
while(t--)
{
num=0;
scanf("%d%d",&s,&p);
for(i=0;i<=p;i++)
{
bin[i]=i;
r[i]=0;
}
for(i=0;i<p;i++)
scanf("%d%d",&x[i],&y[i]);
for(i=0;i<p;i++)
for(j=i+1;j<p;j++)
{
edge[num].u=i;
edge[num].v=j;
edge[num++].len=dist(x[i],y[i],x[j],y[j]);
}
qsort(edge,num,sizeof(edge[0]),cmp);
d=Kruskal();
printf("%.2f\n",sqrt(d));
}
return 0;
}
--------------------------------------------------------------------------------------------------------------------------------------------
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int M=1000000; //定义一个无穷数
const int maxn=502;
int s,p;
bool visit[maxn];
int dist[maxn][maxn];
int lowcost[maxn]; //lowcost[i]记录的是结点i与当前生成的最小生成树的距离
struct node
{
int x;
int y;
}point[maxn];
int length(node p,node q)
{
return (p.x-q.x)*(p.x-q.x)+(p.y-q.y)*(p.y-q.y);
}
void Prim(int v)
{
int i,j,k,min;
for(i=0;i<p;i++)
if(i!=v)
lowcost[i]=dist[0][i];
visit[0]=true;
for(i=1;i<p;i++)
{
min=M;
for(j=0;j<p;j++)
if(lowcost[j]<min && !visit[j])
{
min=lowcost[j];
k=j;
}
visit[k]=true;
for(j=0;j<p;j++)
if(dist[k][j]<lowcost[j] && !visit[j])
lowcost[j]=dist[k][j];
}
}
int main()
{
int i,j,t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&s,&p);
for(i=0;i<maxn;i++)
for(j=0;j<maxn;j++)
dist[i][j]=M;
for(i=0;i<p;i++)
scanf("%d%d",&point[i].x,&point[i].y);
for(i=0;i<p;i++)
for(j=0;j<p;j++)
{
dist[i][j]=length(point[i],point[j]);
dist[j][i]=dist[i][j];
}
memset(visit,0,sizeof(visit));
Prim(0);
sort(lowcost,lowcost+p);
printf("%.2f\n",sqrt((double)lowcost[p-s]));
}
return 0;
}