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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lzyws739307453/article/details/85276483

题目链接: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;
}

猜你喜欢

转载自blog.csdn.net/lzyws739307453/article/details/85276483