CowHurdles
Time Limit: 1000MS | Memory Limit: 65536K |
Total Submissions: 8625 | Accepted: 3795 |
Description
Farmer John wants the cows to prepare for the county jumpingcompetition, so Bessie and the gang are practicing jumping over hurdles. Theyare getting tired, though, so they want to be able to use as little energy aspossible to jump over the hurdles.
Obviously, it is not very difficult for a cow to jump over severalvery short hurdles, but one tall hurdle can be very stressful. Thus, the cowsare only concerned about the height of the tallest hurdle they have to jumpover.
The cows' practice room has N (1 ≤ N ≤ 300) stations, conveniently labeled1..N. A set of M (1 ≤ M ≤ 25,000) one-way paths connects pairsof stations; the paths are also conveniently labeled 1..M. Path i travels from station Si to station Ei and contains exactly one hurdle ofheight Hi (1 ≤ Hi ≤ 1,000,000). Cows must jump hurdlesin any path they traverse.
The cows have T (1 ≤ T ≤ 40,000) tasks to complete. Task i comprises two distinct numbers, Ai and Bi (1 ≤ Ai ≤ N;1 ≤ Bi ≤ N),which connote that a cow has to travel from station Ai to station Bi(by traversingover one or more paths over some route). The cows want to take a path theminimizes the height of the tallest hurdle they jump over when traveling from Ai to Bi . Your job is to write a program thatdetermines the path whose tallest hurdle is smallest and report that height.
Input
* Line 1: Three space-separated integers: N, M, and T
* Lines 2..M+1: Line i+1contains three space-separated integers: Si , Ei , and Hi
* Lines M+2..M+T+1:Line i+M+1 containstwo space-separated integers that describe task i: Ai and Bi
Output
* Lines 1..T: Line i contains the result for task i and tells the smallest possiblemaximum height necessary to travel between the stations. Output -1 if it isimpossible to travel between the two stations.
SampleInput
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
SampleOutput
4
8
-1
Source
USACO 2007 November Silver
算法分析:
让我心痛一夜的习题,本以为是二分加最短路,好怒容易打出来,通过测试样例结果在洛谷上就过了两个点,其他全超时,心碎啊!
先来我的一夜代码(这是不过的,下面有正解)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<string>
#include<cstdlib>
#include<queue>
#include<vector>
#define INF 1e8
#define PI acos(-1.0)
#define MOD 2520
#define E 1e-12
using namespace std;
#define N 350
int n,m,t,h[N][N],d[N][N],sx,ey;
int solve(int maxh)
{
int dis[N][N];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{dis[i][j]=d[i][j];
}
if(dis[sx][ey]!=INF) dis[sx][ey]=INF;
for(int k=1;k<=n;k++)//floyed算法
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
if(i!=k&&j!=i&&j!=k&&dis[i][j]>dis[i][k]+dis[k][j]&&h[i][k]<=maxh&&h[k][j]<=maxh)
{
dis[i][j]=dis[i][k]+dis[k][j];
}
}
//cout<<maxh<<" "<<dis[sx][ey]<<endl;
return dis[sx][ey];
}
int main()
{
while(scanf("%d%d%d",&n,&m,&t)!=EOF)
{
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{d[i][j]=INF;
h[i][j]=INF;
}
int maxx=0;
for(int i=1;i<=m;i++)
{
int x,y,c;
scanf("%d%d",&x,&y);
scanf("%d",&c);
if(c<h[x][y]) h[x][y]=c;
d[x][y]=1;
maxx=max(h[x][y],maxx);
}
for(int i=1;i<=t;i++)
{
scanf("%d%d",&sx,&ey);
if(solve(INF)==INF)
{cout<<-1<<endl;continue; }
int l=0,r=maxx,mid,ans=0;
while(l<=r)
{
mid=(l+r)/2;
if(solve(mid)==INF)
{
l=mid+1;
}
else
{
r=mid-1;
ans=mid;
}
}
if(d[sx][ey]!=INF&&h[sx][ey]!=INF&&h[sx][ey]<mid)
ans=h[sx][ey];
if(ans==0||ans==maxx) cout<<"-1"<<endl;
else printf("%d\n",ans);
}
}
return 0;
}
题意:一条路首先保证栅栏最低的最短路
分析:这时稍微分析一下,考虑i到j这条路径的时候,它的答案一定是 它本身与 从i到j另外的路径上的站台高度的最大值。所以如果我们将最短路的定义改为这条路径上最高的栅栏的高度,那么根据上面的分析,更新答案的时候就为
dis[i][j]=min(dis[i][j],max(dis[i][k],dis[k][j]));
如上方叙述执行floyd,即可在n^3的时间内求出所有路径的答案,最后每组询问o(1)出解即可
代码实现:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 305
using namespace std;
int n,m,k1;
#define INF 1e8
int dis[maxn][maxn];
int main()
{
memset(dis,0x3f,sizeof(dis));
scanf("%d%d%d",&n,&m,&k1);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
dis[x][y]=z;
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=k && k!=j && i!=j)
{
if(dis[i][k]<INF && dis[k][j]<INF)
{
dis[i][j]=min(dis[i][j],max(dis[i][k],dis[k][j]));
}
}
for(int i=1;i<=k1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
if(dis[x][y]>INF)
{
printf("-1\n");
continue;
}
printf("%d\n",dis[x][y]);
}
return 0;
}