1. 程式人生 > >Vijos - 想越獄的小杉(最短路)

Vijos - 想越獄的小杉(最短路)

題目連結:https://vijos.org/p/1391

背景

這次小杉來到了經典美劇《越獄》的場景裡……
他被抓起來了(-.-幹嘛幻想這麼鬱悶的場景……)。
小杉身為新一代的Scofield,在挖了半個月之後終於挖通牢房裡的地道。
在地道里,無數的管道路線困惑了他。
(若對情節有任何疑問,請觀看原劇)

題目描述

小杉看了看自己的紋身,明白了整個管道網是由N個小房間和若干小房間之間的單向的管道組成的。
小房間編號為不超過N的正整數。
對於某個管道,小杉只能在人品不超過一定程度時通過。
小杉一開始在房間1,現在小杉想知道,每個小房間他最多能夠以人品多少的狀態到達。
注意,小杉的人品在出發以後是不會改變的。

輸入格式

每組測試資料的
第一行有一個正整數N(1<=N<=2000)。
接下來若干行描述管道,每行三個正整數A,B,R(1<=A,B<=N),表示A房間有一條到達B房間的管道,且小杉的人品不超過R時可以通過(注意從B房間不可由此管道到達A房間,即管道是單向的),整個輸入資料以一行0 0 0結束。
特別地,對於30%的資料,有N<=100

輸出格式

對每組測試資料輸出N-1行,分別表示對於2到N號的小房間,小杉最多能夠以人品多少的狀態到達。

樣例輸入

4
1 2 30
1 3 20
2 3 25
3 4 30
2 4 20
0 0 0

樣例輸出

30
25
25

限制

每個測試點1s

提示

對於樣例資料:
小杉最多能夠在人品為30的情況下到達小房間2(1->2)
小杉最多能夠在人品為25的情況下到達小房間3(1->2->3)
小杉最多能夠在人品為25的情況下到達小房間4(1->2->3->4)

解題思路

這道題考察的還是最短路問題,只不過求的是最大的,可以用迪傑斯特拉最短路徑演算法做,只不過要變一下條件。我們知道,求可以通過的最多人品,可以求從1號到n號可以通過的每個房間的最多人品,即求每條路線上子房間的最少人品數(類似於木桶原理),故一部分核心程式碼為:

for (k = 0; k < n; k++)
{
    if (map[data][k] < inf)
    {
        ans = min(dis[data], map[data][k]);
        if (!vis[k] && dis[k] < ans)
            dis[k] = ans;
    }
}

#include <stdio.h>
#define min(a, b) a < b ? a : b
const int inf = 99999999;
int t, map[2010][2010], vis[2010], dis[2010], n, m;
void Dijkstra() {
    int data = 0, max, ans, i, j, k;
    for (i = 0; i < n; i++) {
        dis[i] = map[0][i];
        vis[i] = 0;
    }
    vis[0] = 1;
    for (i = 0; i < n; i++) {
        max = -inf;
        for (j = 0; j < n; j++) {
            if (!vis[j] && dis[j] > max) {
                max = dis[j];
                data = j;
            }
        }
        vis[data] = 1;
        for (k = 0; k < n; k++) {
            if (map[data][k] < inf) {
                ans = min(dis[data], map[data][k]);
                if (!vis[k] && dis[k] < ans)
                    dis[k] = ans;
            }
        }
    }
}
int main() {
    int t1, t2, t3;
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n; j++)
                map[i][j] = 0;
        while (scanf("%d%d%d", &t1, &t2, &t3), t1 + t2 + t3)
            map[t1 - 1][t2 - 1] = t3;
        Dijkstra();
        for (int i = 1; i < n; i++)
            printf("%d\n", dis[i]);
    }
    return 0;
}