【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;
}

 

posted @ 2018-02-01 19:56  SAKURA12  阅读(210)  评论(0编辑  收藏  举报