输入一个\(C\)个点\(S\)条边 \((C<=100)\) \((S<=1000)\)的无向带权图,边权表示该路径上的噪声值。当噪声太大时,耳膜可能会收到损伤,因此当你从某点去往另外一个点时,老是但愿路上通过的噪声最大值最小。输入一些询问,每次询问两个点,求出这两点间最大噪声值最小的路径。输出其最大噪声值c++
\(Floyd\)算法
本题的作法十分简单:直接用\(Floyd\)算法,可是要把\(+\)改为\(min\),\(min\)改为\(max\)。spa
为何能够这样作呢? 大部分题解都没给出证实,这里给出证实过程code
无论是\(Floyd\)仍是\(Dijkstra\)算法,都是基于这样一个事实:对于任意一条至少包含两条边的路径i->j
,必定存在某一个中间点k
使得i->j
的总长度等于i->k
与k->j
的长度之和。对于不一样的点k
,i->k
和k->j
的长度之和可能不一样,最后还须要取一个最小值才是i->j
的最短路径。把刚才推理中“之和”与“取最小值”换成“取最小值”和“取最大值”,推理仍然适用get
#include<bits/stdc++.h> using namespace std; int n,m,Q; int g[110][110]; int T; inline int read() { int tot=0; char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c>='0'&&c<='9') { tot=tot*10+c-'0'; c=getchar(); } return tot; } int main() { n=read();m=read();Q=read(); while(1) { T++; memset(g,0x3f,sizeof(g)); for(int i=1;i<=m;i++) { int x=read(),y=read(),z=read(); g[x][y]=z; g[y][x]=z; } for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { g[i][j]=min(g[i][j],max(g[i][k],g[k][j])); } } } cout<<"Case #"<<T<<endl; while(Q--) { int x=read(),y=read(); if(g[x][y]==0x3f3f3f3f)cout<<"no path\n"; else cout<<g[x][y]<<endl; } n=read();m=read();Q=read(); if(n||m||Q)cout<<endl; else break; } return 0; }