【Dijkstra算法变式】POJ2253
题目:http://poj.org/problem?id=2253
思路
我给翻译翻译,这题实际就是求出一条从A到B的路径,其中路径上的边权值的上界要最小,然后返回这个最小值.
乍一看它和Dijkstra算法无关,实际上我们只要把松弛边操作修改一下就行了.我们为每个顶点v规定一个属性maxleap
,这个属性就是我们所求的属性,即最终我们的程序输出就是B.maxleap
.
我们给每个顶点的maxleap
属性初始化为正无穷,而起始节点A的属性初始化为0.
我们修改Dijkstra算法的松弛边操作,即
对于边vi来说,我们可以修正i
的maxleap
属性:
maxLeap[i]=min(
maxLeap[i],
max(maxLeap[v],w[v][i])
);
max(maxLeap[v],w[v][i])
表示,计算出来的i的属性应该是在v的属性和该边vi的权值中的较大值
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define INTMAX 0x3f3f3f3f
typedef pair<int,int> pii;
typedef long long ll;
#define x first
#define y second
int num_vec;
pii positions[205];
int w[205][205];
int maxLeap[205];
void debug()
{
for(int i=0;i<num_vec;i++)
{
for(int j=0;j<num_vec;j++)
cout<<w[i][j]<<" ";
cout<<endl;
}
}
void init()
{
memset(maxLeap,INTMAX,sizeof(maxLeap));
}
void input()
{
for(int i=0;i<num_vec;i++)
scanf("%d%d",&positions[i].x,&positions[i].y);
for(int i=0;i<num_vec;i++)
for(int j=0;j<num_vec;j++)
w[i][j]=(positions[i].x-positions[j].x)*(positions[i].x-positions[j].x)
+(positions[i].y-positions[j].y)*(positions[i].y-positions[j].y);
}
bool mycmp(const int & a,const int & b)
{
return maxLeap[a]<maxLeap[b];
}
int dij()
{
maxLeap[0]=0;
vector<int>Q(num_vec);
for(int i=0;i<num_vec;i++)
Q[i]=i;
while(Q.size())
{
vector<int>::iterator p=min_element(Q.begin(),Q.end(),mycmp);
int v=*p;
if(v==1)
return maxLeap[1];
Q.erase(p);
for(int i=0;i<num_vec;i++)
{
maxLeap[i]=min(maxLeap[i],max(maxLeap[v],w[v][i]));
}
}
return INTMAX;
}
int solve()
{
init();
input();
//debug();
return dij();
}
int main()
{
int i_case=1;
scanf("%d",&num_vec);
while (num_vec)
{
printf("Scenario #%d\n",i_case++);
printf("Frog Distance = %.3f\n",sqrt(solve()));
printf("\n");
scanf("%d",&num_vec);
}
return 0;
}