【USACO 2007 Nov】奶牛跨栏 Cow Hurdles
题目描述
约翰家的奶牛正在准备跨栏比赛。对奶牛来说,跳过几个矮栅栏是容易的,但一个高栅 栏却很难跳过。于是,奶牛们关心的是一条路线上所有栅栏中的最高高度。
奶牛的训练场中有N个站台,标号为1到N。站台之间有M条单向道路,第i条道路的起点 是Si,终点是Ei,道路上栅栏的高度为Hi。
奶牛们有T个训练任务要完成。第i个任务要求奶牛必须从站台Ai跑到站台Bj,奶牛可以自由选择路线,为了寻找最轻松的路线,绕点远路可能也是值得的。你的任务就是写一个程序,帮助奶牛尽可能地降低每个训练任务会遇到的最高栅栏的高度。
输入格式
第一行:三个用空格分开的整数: N,M和T,1 ≤ N ≤ 300,1 ≤ M ≤ 25000, 1 ≤ T ≤ 40000
第二行到M + 1行:第i + 1行有三个用空格分开的整数: Si,Ei和Hi,1 ≤ Si ≤ N, 1 ≤ Ti ≤ N,1 ≤ Hi ≤ 106
第M + 2行到M + T + 1行: 第i + M + 1行有两个用空格分开的整数: Ai和Bi, 1 ≤ Ai ≤ N, 1 ≤ Bi ≤ N
输出格式
第一行到第T行:每行一个整数,表示起点为Ai,终点为Bi的路线中最高的栅栏高度的 最小值,如果从Ai到Bi不存在路线,输出−1
样例输入
5 6 3
1 2 12
3 2 8
1 3 5
2 5 3
3 4
4 2
4 8
3 4
1 2
5 1
样例输出
4
8
-1
提示
第一个查询:直接从3到4即可;
第二个查询:可以直接到2,但还是先到3,再到2为好
题解
a[i][j]存从i到j的最高栅栏的最小值。
a[i][j]初始为无穷大,读入时,把a[Si][Ei]更新为Hi
读完后,枚举i和j之间的中间点k,i-j的最高栅栏=max(i-k的最高栅栏,k-j的最高栅栏),这样得出一条从i经k到j的路线上的最高栅栏,若比当前a[i][j]小,则更新。
最后如果a[i][j]为无穷大,说明a[i][j]没被更新过,那么不存在从i到j的路线。
#include <cstdio> int a[305][305]; int min(int x,int y) { return x<=y?x:y; } int max(int x,int y) { return x>=y?x:y; } int main() { int n,m,s,e,t,i,j,k,h; scanf("%d%d%d",&n,&m,&t); for (i=1;i<305;i++) for (j=1;j<305;j++) a[i][j]=1e9; for (i=1;i<=m;i++) { scanf("%d%d%d",&s,&e,&h); a[s][e]=h; } for (k=1;k<=n;k++) for (i=1;i<=n;i++) for (j=1;j<=n;j++) a[i][j]=min(a[i][j],max(a[i][k],a[k][j])); for (i=1;i<=t;i++) { scanf("%d%d",&s,&e); printf("%d\n",a[s][e]!=1e9?a[s][e]:-1); } return 0; }