Description
问题描述:链接
思路
题目的意思是青蛙想从第一块石头跳到第二块石头,中间有许多垫脚石,求能跳到第二块石头的路上至少需要跳多远。拿第二个样例来说,顶点 1 到顶点 2 有两条路分别为:1(根号2)3(根号2)2 和 1(2)2 ,括号里的值表示相邻两点的距离。其中前一条路青蛙至少得具有根号2的跳跃能力才能到达第二块石头,后一条路需要具有2的跳跃能力。由于两条路都能到达顶点2,那么青蛙的跳跃能力只需要根号2即可。
实质上,这道题就是求所有通路的最大边的最小值。
我们让 d 数组中存储所有从顶点1到顶点v的可达路径中最大边的最小值,那么依旧可以使用 Dijkstra 贪心得到顶点1到顶点2的可达路径中最大边的最小值。由于比较的是某条边的权,所以需要将松弛条件改成如下形式:
d[v] > max( d[u], w(u, v) )
AC代码:
#include<iostream> #include<algorithm> #include<cstring> #include<cmath> #include<iomanip> using namespace std; #define INF 0x3f3f3f3f const int MAX_N = 210; int n; int x[MAX_N], y[MAX_N]; //u点到v点的距离 double w (int u, int v) { return sqrt((double)(x[v] - x[u])*(x[v] - x[u]) + (y[v] - y[u])*(y[v] - y[u])); } double d[MAX_N]; bool vis[MAX_N]; void dijkstra (const int& s) { for (int i = 1; i <= n; ++i) d[i] = INF, vis[i] = false; d[1] = 0; for (int i = 1; i <= n; ++i) { double min_d = INF; int u; for (int j = 1; j <= n; ++j ) { if ( !vis[j] && d[j] < min_d ) { min_d = d[j]; u = j; } } vis[u] = true; //图为无向图,所有顶点都有 n-1 条邻接边 for (int v = 1; v <= n; ++v) { if ( d[v] > max (d[u], w(u, v) ) ) { d[v] = max (d[u], w(u, v) ); } //d[v] = min (d[v], max(d[u], w(u, v))); } } } int main (void) { int test_num = 0; while (cin >> n && n ) { for (int i = 1; i <= n; ++i) { cin >> x[i] >> y[i]; } dijkstra (1); cout << "Scenario #" << ++test_num << endl << "Frog Distance = " << setiosflags(ios::fixed) << setprecision(3) << d[2] << endl << endl; } return 0; }