【Luogu T145192】 【2020.8.23NOIP模擬賽】最優路線
阿新 • • 發佈:2020-08-23
題目大意:
一個 \(n\) 個點 \(m\) 條邊的無重邊無自環的無向圖,點有點權,邊有邊權,定義一條路徑的權值為路徑經過的點權的最大值乘邊權最大值。求任意兩點間的權值最小的路徑的權值。
正文:
一道 Floyd 練手題,存下每條路的最大點權與邊權,在 Floyd 的時候一起運算,Floyd 時升序列舉點權作為中點。
程式碼:
int main() { scanf ("%d%d", &n, &m); memset(mp, 0x7f, sizeof mp); memset(me, 0x7f, sizeof me); memset(dis, 0x7f, sizeof dis); for(int i = 1; i <= n; i++) scanf("%d", &val[i]), a[i].val = val[i], a[i].id = i; sort(a + 1, a + 1 + n, cmp); for(int i = 1; i <= m; i++) { int u, v; ll w; scanf ("%d%d%lld", &u, &v, &w); me[u][v] = me[v][u] = w; mp[u][v] = mp[v][u] = max(val[u], val[v]); vis[u][v] = vis[v][u] = 1; dis[u][v] = dis[v][u] = (ll)mp[v][u] * me[u][v]; } for(int K = 1; K <= n; K++) for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { int k = a[K].id; if(!vis[i][k] || !vis[k][j] || i == j) continue; int maxp = max(mp[i][k], mp[k][j]), maxe = max(me[i][k], me[k][j]); if((ll)maxp * maxe < dis[i][j]) { dis[i][j] = (ll)maxp * maxe; mp[i][j] = maxp; me[i][j] = maxe; vis[i][j] = 1; } } for(int i = 1; i <= n; i++) { for(int j = 1; j <= n; j++) { if(i == j) printf("0 "); else if(vis[i][j]) printf("%lld ", dis[i][j]); else printf("-1 "); } puts(""); } return 0; }