您的位置:首页 > 其它

POJ 2235 Frogger 最小生成树 Kruskal && Prim

2015-08-13 19:05 495 查看
Frogger

Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 30433 Accepted: 9808
Description

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

注-此题为:
 POJ 2235 Frogger 
题意:

       给出两只青蛙的坐标A、B,和其他的n-2个坐标,任一两个坐标点间都是双向连通的。

显然从A到B存在至少一条的通路,每一条通路的元素都是这条通路中前后两个点的距离,

这些距离中又有一个最大距离。

要求:        他最小的弹跳距离是多少(即最短路径中的最长边)。

    在生成最小生成树时,只要 A,B 连一起后,其余的点就不用再连 (不需要把所有的点都连起来) 

    最小生成树    Kruskal     rim      模板

已AC代码:(Kruskal)

#include<cstdio>
#include<cstring>
#include<cmath>
#define M 25000
#include<algorithm>
using namespace std;

int per[300];   // 并查集
int x[3000],y[300];
int n,m;

struct node{
int u,v;
double w;   //w为距离
}s[M];

bool cmp(node a,node b)
{
return a.w<b.w;
}

double dlen(int i,int j)
{
return sqrt( 1.0*( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) ) );
}

void into()     //初始化
{
for(int i=0;i<=n;++i)
per[i]=i;
}

int find(int x)    // 查找根节点
{
return x==per[x]?x:per[x]=find(per[x]);
}

bool join(int a,int b)    //合并根节点,并判断是否成环
{
int fa=find(a);
int fb=find(b);
if(fa!=fb)
{
per[fa]=fb;
return true;
}
return false;
}

int main()
{
int i,j,cas=1;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;++i)
scanf("%d%d",&x[i],&y[i]);
int k=0;
for(i=1;i<n;++i)   //读入数据
{
for(j=i+1;j<=n;++j)
{
s[k].u=i;
s[k].v=j;
s[k].w=dlen(i,j);
k++;
}
}
into();   //初始化根节点
sort(s,s+k,cmp);    //按距离从小到大排序
for(i=0;i<k;++i)
{
if(join(s[i].u,s[i].v))
{
if(find(1)==find(2))   //连到 2 后就不再连,(不一定把所有的点都连起来)
break;
}
}

printf("Scenario #%d\n",cas++);
printf("Frog Distance = %.3f\n",s[i].w); //已经排过序  s[i].w即最短路径中的最长边
printf("\n");
}
return 0;
}


已AC代码:( Prim)

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define INF 0xfffffff
using namespace std;

double map[300][300],low[300];
int n,vis[300];  //map二维数组存图,low记录每2个点间最小权值,vis标记某点是否已访问
int x[3000],y[300];

double dlen(int i,int j)
{
return sqrt( 1.0*( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) ) );
}

double prim()
{
memset(vis,0,sizeof(vis));
int i,j,pos,t;
double MIN,MAX=0;

for(i=1;i<=n;++i)  	//从某点开始,分别标记vis和记录该点pos
low[i]=map[1][i];  	//第一次给low数组赋值 map的第一行
vis[1]=1;pos=1;t=0;

for(i=1;i<n;++i)   //再运行n-1次,一次找一个最小
{
MIN=INF;
for(j=1;j<=n;++j)
{
if(vis[j]==0&&low[j]<MIN)
{
MIN=low[j];  // 找出最小值min,记录位置pos
pos=j;
}
}

if(MIN>MAX)  //最小生成树的 最大边
MAX=MIN;

if(pos==2)  //连到 2 后就不再连,(不一定把所有的点都连起来)
return MAX;

vis[pos]=1;   //标记该点已访问
for(j=1;j<=n;++j)    //更新权值low 把 map的 pos 行中比对应的 low 小的赋给low
if(vis[j]==0&&low[j]>map[pos][j])
low[j]=map[pos][j];
}
}

int main()
{
int i,j,cas=1;
double t;
while(scanf("%d",&n),n)
{
for(i=1;i<=n;++i)
for(j=1;j<=n;++j)
map[i][j]=0;
for(i=1;i<=n;++i)
scanf("%d%d",&x[i],&y[i]);

for(i=1;i<n;++i)  //建图
for(j=i+1;j<=n;++j)
map[i][j]=map[j][i]=dlen(i,j);

t=prim();
printf("Scenario #%d\n",cas++);
printf("Frog Distance = %.3lf\n",t);
printf("\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息