您的位置:首页 > 其它

POJ 2253 连通图的最小边问题(转载)

2010-04-25 20:29 295 查看
/*Dij的变形,这道题目的意思大致是,给你起点和终点,还有一些可用来中间过度的点,首先保证你能够跳跃到终点,
同时还要保证你的跳跃跨度最小,也就是从起点到终点路径上的最大的那条边要尽量小,这个有点绕,所以我把这道题
目改一下
等价题:假设你在玩一个闯关游戏,目的是到达终点闯关,走哪条路无关紧要,你把那些点之间的路径看成是怪物,路
径长度看成是怪物的能量值,如果你想击败怪物顺利闯关的话,你的能量值必须高于怪物的能量值,当然获得能量值是
需要付出代价的,现在你想用最少的代价通关,求这个最小的能量值是多少?不难想到,此题可以用Dij来解,只需要
把sum改成max即可。不得不提的是,这里不是求最短路径,而是求连通图的最小边的问题,它们都可以用Dij,个人感觉
它们似乎是平行的关系,只不过是Dij大环境下的2个变种罢了。在最短路径问题中,dis[i]数组中存储的是,i点到原点
的最小距离,而在连通图最小边问题中,dis[i]数组中存储的是i点到周围任何一个点的最小距离(当然这个距离是通过不
断的松弛,最后才得到的*/

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <limits> //引入limits头文件
using namespace std;
typedef struct stone
{
int xi;
int yi;
}stone;
#define arraysize 201
stone stones[arraysize];
double dis[arraysize][arraysize];
bool final[arraysize];
double d[arraysize];
int n;
int num;
double max = numeric_limits<double>::max(); //double 的最大值
void Dij()
{
memset(final,0,sizeof(final));
memset(d,0,sizeof(d));
double fgdistance = 0;
for(int i3=1;i3<n+1;++i3)
{
d[i3] = dis[1][i3];
}
final[1] = true;
d[1] = 0;
for(int i=1;i<n;++i)
{
double min = max;
int v = 1;
for(int i1=2;i1<n+1;i1++)
{
if(!final[i1] && min>d[i1])
{
min = d[i1];
v = i1;
}
}
final[v] = true;
//此处是关键
if(min>fgdistance)
{
fgdistance = min;
}
if(v==2)
break;
for(int i2=2;i2<n+1;i2++)
{
if(!final[i2])
{
if(dis[v][i2]<d[i2])
{
d[i2] = dis[v][i2];
}
}
}
}
printf("Scenario #%d\n",num);
printf("Frog Distance = %.3f\n\n",fgdistance);
}
int main()
{
stone start,end;
num = 0;
//freopen("1.txt","r",stdin);
while(scanf("%d",&n) && n!=0)
{
int xi,yi;
for(int i=1;i<n+1;++i)
{
scanf("%d%d",&xi,&yi);
stones[i].xi = xi;
stones[i].yi = yi;
}
for(int i1=1;i1<n+1;++i1)
{
for(int i2=1;i2<n+1;++i2)
{
int xm = stones[i1].xi - stones[i2].xi;
int ym = stones[i1].yi - stones[i2].yi;
dis[i1][i2] = sqrt(double(xm*xm+ym*ym)); //此处别忘了加double,否则会出现编译时错误
dis[i2][i1] = dis[i1][i2];
}
}
num++;
Dij();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: