POJ2253
Freddy青蛙坐在湖的中間。突然他發現,Fiona 青蛙坐在另一塊。他計劃去看望她,但由於水是髒的,他想避免游泳到達。
不幸的是,Fiona的石頭超出了他的跳躍範圍。因此,Freddy必須使用其他石頭作爲中間點。
因此他需要跳過很多塊石頭,很明顯,他的最長跳躍距離應該要是相隔最長的兩個石頭的距離。
青蛙的距離被定義爲在所有可能的路徑之間的最長跳躍距離的最小值。
給定Freddy青蛙和Fiona青蛙所在石頭的座標,和其他石頭的座標,請計算青蛙距離。
輸入格式
輸入將包含一個或多個測試用例。每一個測試用例的第一行表示石頭個數n(2<=n<=200)。接下來的n行每行包含兩個整數xi,yi(0 <=xi,yi<= 1000)代表石頭的座標
第一行座標是Freddy的石頭,第二行座標是Fiona的石頭,剩下n-2行是其他石頭的座標。每一組測試案例間都有一個空行。N爲0表示結束。
輸出
每組測試數據輸出兩行,第一行輸出Scenario #x,第二行輸出Frog Distance = y,其中x爲第幾組測試數據,y表示青蛙距離,保留三位小數。最後請輸出一個空行
樣例輸入
2
0 0
3 4
3
17 4
19 4
18 5
0
樣例輸出
Scenario#1
FrogDistance = 5.000
Scenario#2
FrogDistance = 1.414
思路很簡單,只是在做克魯斯卡爾的時候不斷地添加邊,直到第一個點和第二個點被添加在一起,想想爲什麼這樣就可以了??
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<limits.h>
#include<iostream>
#include<math.h>
using namespace std;
struct edge{
int x,y;
double v;
}e[50001];
double map[205][205];
int x[205],y[205],cnt=0,f[50001];
double dis(int a,int b)
{
return sqrt((x[a]*1.0-x[b]*1.0)*(x[a]*1.0-x[b]*1.0)+(y[a]*1.0-y[b]*1.0)*(y[a]*1.0-y[b]*1.0));
}
bool cmp(edge a,edge b)
{
return a.v<b.v;
}
int find(int x)
{
if(x!=f[x])f[x]=find(f[x]);
return f[x];
}
int main()
{
int n,num=0;
while(cin>>n,n)
{
num++;
memset(e,127,sizeof(e));
int i,j,k=0;
for(i=1;i<=n;i++)cin>>x[i]>>y[i];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
{
map[i][j]=map[j][i]=dis(i,j);
if(i<j)
{
e[++cnt].v=map[i][j];
e[cnt].x=i;
e[cnt].y=j;
}
}
sort(e+1,e+1+cnt,cmp);
for(i=1;i<=n;i++)f[i]=i;
double d=0;
for(i=1;i<=cnt;i++)
{
int fa=find(e[i].x),fb=find(e[i].y);
if(fa!=fb)
{
k++;
d=e[i].v;
f[fa]=fb;
}//在這之前都是克魯斯卡爾的算法
if(find(1)==find(2))//精髓所在!自己體悟
{
printf("Scenario #%d\nFrog Distance = %.3f\n\n",num,d);
break;
}
if(k==n-1)break;
}
}
return 0;
}