题意: 从起点到终点,让这条路径上的每一条边都尽量短(不是求总路径最短)。
做法: 运用kruscal的做法,每次构造最短边,知道起点和终点在一个集合中,那么当前的最短边就是 所求结果!
代码:
#include<stdio.h>
#include<algorithm>
#include<cmath>
using namespace std;
int fa[100005],son[100005];
struct Point
{
double x,y; //开始没注意坐标是 实数,错了几次
}point[100005];
struct Node
{
int a,b; //aµã£¬bµã
double v;
}e[100005];
double dis(int a,int b)
{
return sqrt( (point[a].x-point[b].x)*(point[a].x-point[b].x)+
(point[a].y-point[b].y)*(point[a].y-point[b].y) );
}
bool cmp(struct Node aa,struct Node bb)
{
return aa.v<bb.v;
}
int find(int x)
{
return (x==fa[x]?x:find(fa[x]) );
}
int join(int x,int y)
{
x=find(x);
y=find(y);
if(x==y) return 0;
if(son[x]>son[y])
{
son[x]+=son[y];
fa[y]=x;
}else{
son[y]+=son[x];
fa[x]=y;
}
return 1;
}
int main()
{
// freopen("data.in","r",stdin);
// freopen("da1.out","w",stdout);
int i,j,n,len,num,ncase;
double ans;
ncase=0;
while(scanf("%d",&n))
{
if(n==0) break;
for(i=1;i<=n;i++)
scanf("%lf%lf",&point[i].x,&point[i].y);
num=0;
for(i=1;i<=n;i++)
for(j=i+1;j<=n;j++)
{
num++;
e[num].a=i;
e[num].b=j;
e[num].v=dis(i,j);
}
sort(e+1,e+num+1,cmp);
for(i=1;i<=n;i++)
fa[i]=i,son[i]=1;
len=0;
for(i=1;i<=num;i++)
if(join(e[i].a,e[i].b))
{
len++;
// printf("e%d=%.2f\n",i,e[i].v);
if(find(1)==find(2)) {ans=e[i].v; break; } // 此处判断条件出错,不是要构造完全的生成树,只要起点、终点在一个集合中就行!
}
printf("case #%d : %.3lf\n\n",++ncase,ans);
}
return 0;
}