POJ-2253||ZOJ-1942
Frogger
Freddy Frog is sitting on a stone in the middle of a lake. Suddenly he notices Fiona Frog who is sitting on another stone. He plans to visit her, but since the water is dirty and full of tourists’ sunscreen, he wants to avoid swimming and instead reach her by jumping.
Unfortunately Fiona’s stone is out of his jump range. Therefore Freddy considers to use other stones as intermediate stops and reach her by a sequence of several small jumps.
To execute a given sequence of jumps, a frog’s jump range obviously must be at least as long as the longest jump occuring in the sequence.
The frog distance (humans also call it minimax distance) between two stones therefore is defined as the minimum necessary jump range over all possible paths between the two stones.
You are given the coordinates of Freddy’s stone, Fiona’s stone and all other stones in the lake. Your job is to compute the frog distance between Freddy’s and Fiona’s stone.
Input
The input will contain one or more test cases. The first line of each test case will contain the number of stones n (2<=n<=200). The next n lines each contain two integers xi,yi (0 <= xi,yi <= 1000) representing the coordinates of stone #i. Stone #1 is Freddy’s stone, stone #2 is Fiona’s stone, the other n-2 stones are unoccupied. There’s a blank line following each test case. Input is terminated by a value of zero (0) for n.
Output
For each test case, print a line saying “Scenario #x” and a line saying “Frog Distance = y” where x is replaced by the test case number (they are numbered from 1) and y is replaced by the appropriate real number, printed to three decimals. Put a blank line after each test case, even after the last one.
Sample Input
2
0 0
3 4
3
17 4
19 4
18 5
0
Sample Output
Scenario #1
Frog Distance = 5.000
Scenario #2
Frog Distance = 1.414
题目链接:
http://poj.org/problem?id=2253
题意:
一只青蛙在一块石头上,它要去另一个石头上找她老婆,它与它老婆之间还有其他石头,青蛙可以跳到石头上中转,可以跳很多次,但是要求每次起跳的距离尽量短一些,求最长的一段距离是多大,(就比如你要去距离你十米的一个地方,你可以步子很大的跨过去,但是本题要求你可以步子很小的走很多步,求最大的步子是多大)。
我(弱鸡)想到了用最小生成树,有的大佬用了dijkstra。
手头刚好有一个Kruskal板子,之前写过一个求最小生成树中最长的路的题,以为和这个题一样,改了改板子过了样例就提交了,果不其然wa了,wa的莫名其妙,然后看了看数据范围,发现数组结构体都开小了,然后又觉得wa的理所当然,然后又提交,又wa的莫名其妙。
仔细考虑过后,越发的觉得自己头脑简单,完全不可能抗衡充满“心机”的算法题。还是自己太年轻。
本题的正解为:不一定要把全部的石子都走一遍(之前的想法),将两点之间的距离从小到大排好序后,往集合里面丢,一旦发现青蛙起点石头和他老婆的石头到了一个集合里面(find(0)==find(1))记录下此时丢入集合中的那条边的距离即可,return输出该值即可!
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
int n,m;
const int inf = 0x3f3f3f3f;
const int N =350;
const int M =50500;
struct edge {
int a, b;
double v;
friend bool operator<(const edge A,edge B) {
return A.v<B.v;
}
} e[M];
int fa[N];
void init() {
for(int i=0; i<=n; ++i)
fa[i]=i;
}
int find(int x) {
if(x==fa[x])return x;
else {
fa[x]=find(fa[x]);
return fa[x];
}
}
int unito(int x,int y) {
int A=find(x);
int B=find(y);
if(A!=B) {
fa[A]=B;
return 1;
}
return 0;
}
struct node {
int x,y;
} zz[N];
double sss(node a,node b) {
return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
double Kruksl() {
for(int i=1; i<=n; ++i) {
scanf("%d %d",&zz[i].x,&zz[i].y);
}
int cut=1;
for(int i=1; i<=n; ++i) {
for(int j=i+1; j<=n; ++j) {
double ans=sss(zz[i],zz[j]);
e[cut].a=i;
e[cut].b=j;
e[cut++].v=ans;
}
}
m=cut;
sort(e,e+m);
double sum=0;
for(int i=0; i<m; ++i) {
if(unito(e[i].a,e[i].b)) {
if(e[i].v>sum){
sum=e[i].v;
}
}
}
return sum;
}
int main() {
int k=1;
while(scanf("%d",&n)&&n) {
init();
double ans=Kruksl();
printf("Scenario #%d\n",k++);
printf("Frog Distance = %.3f\n\n",sqrt(ans));
}
return 0;
}
年少不读书,竟然(不知天高地厚)打acm。