您的位置:首页 > 其它

紫书例题 11-5 Uva 10048 Floyd变形或者Kruskal离线

2017-01-29 15:22 429 查看
题意:

输入一个C个点S条边(C≤100,S≤1000)的无向带权图,边权表示该路径上的噪声值。

当噪声值太大时,耳膜可能会受到伤害,所以当你从某点去往另一个点时,总是希望路上经

过的最大噪声值最小。输入一些询问,每次询问两个点,输出这两点间最大噪声值最小的路

路径。

解题思路:

本题的做法十分简单:直接用floyd算法,但是要把加法改成min,min改成max。为什么可以

这样做呢?不管是floyd算法还是dijkstra算法,都是基于这样一个事实:对于任意一条至少包含两条边的路径i->j,一定存在一个中间点k,使得i->j的总长度等于i->k与k->j的长度之和。对于不同的点k,i->k和k->j的长度之和可能不同,最后还需要取一个最小值才是i->j的最短路径。把刚才的推理中“之和”与“取最小值”换成“取最小值”和“取最大值”,推理仍然适用。这个是白书的经典做法,还有另外一种方法是Kruskal离线的做法,可以看这个博客:这里

我这里只写了Floyd变形的写法,Kruskal的写法就没写了。

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 105;
const int inf = 1e8;
int n, m, q, ks, f[maxn][maxn];

int main(){
while(scanf("%d%d%d", &n, &m, &q) != EOF)
{
if(n == 0 && m == 0 && q == 0) break;
for(int i = 1; i < maxn; i++){
f[i][i] = inf;
for(int j = i + 1; j < maxn; j++){
f[i][j] = f[j][i] = inf;
}
}
int a, b, c;
for(int i = 0; i < m; i++){
scanf("%d%d%d", &a, &b, &c);
f[a][b] = f[b][a] = c;
}
for(int k = 1; k <= n; k++){
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
f[i][j] = min(f[i][j], max(f[i][k], f[k][j]));
}
}
}
if(ks > 0) printf("\n");
printf("Case #%d\n", ++ks);
while(q--){
int u, v;
scanf("%d%d", &u, &v);
if(f[u][v] != inf){
printf("%d\n", f[u][v]);
}
else{
printf("no path\n");
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: