POJ 2253 连通图的最小边问题


/*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;
}

你可能感兴趣的:(poj)