給定城市地圖(節點為路口,邊為街道,權重為分貝值)。從路口 A 到 G,路徑上的**最大聲強**決定你必須忍受的音量。求任意兩點間路徑的**最小可能最大聲強**(即最小化路徑上的最大邊權)。若無路徑輸出 "no path"。
標準 Floyd 求最短路(邊權和最小)。本題需求**最小化路徑上的最大邊權**,轉移方程:
dis[i][j] = min(dis[i][j], max(dis[i][k], dis[k][j]));
dis[i][j]:i 到 j 的最小最大聲強。max(dis[i][k], dis[k][j])。dis[i][j] = INF,dis[i][i] = 0。dis[u][v] = dis[v][u] = w。k, i, j 執行變形 Floyd。dis[a][b](若為 INF 則 "no path")。#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int INF = 20000000;
const int MAXC = 105;
int dis[MAXC][MAXC];
int main() {
int C, S, Q, cas = 1;
while (scanf("%d%d%d", &C, &S, &Q) == 3 && (C || S || Q)) {
if (cas != 1) printf("\n");
printf("Case #%d\n", cas++);
for (int i = 1; i <= C; i++)
for (int j = 1; j <= C; j++)
dis[i][j] = (i == j) ? 0 : INF;
for (int i = 0; i < S; i++) {
int u, v, w; scanf("%d%d%d", &u, &v, &w);
dis[u][v] = dis[v][u] = w;
}
// Floyd 變形
for (int k = 1; k <= C; k++)
for (int i = 1; i <= C; i++)
for (int j = 1; j <= C; j++)
dis[i][j] = min(dis[i][j], max(dis[i][k], dis[k][j]));
for (int i = 0; i < Q; i++) {
int a, b; scanf("%d%d", &a, &b);
if (dis[a][b] == INF) printf("no path\n");
else printf("%d\n", dis[a][b]);
}
}
return 0;
}
max 代替 +,min 保持不變。若邊數極少(稀疏圖),可用 **Kruskal 重構樹** 或 **最小生成樹 + LCA** 實現 O((V+E) log V) 查詢,但 C=100 時 Floyd 最簡潔好寫。