背景
这次小杉来到了经典美剧《越狱》的场景里……
他被抓起来了(-.-干嘛幻想这么郁闷的场景……)。
小杉身为新一代的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;
}