1012: City Tour
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 63 Solved: 11
[Submit][Status][Web Board]
Description
Alice想要从城市A出发到城市B,由于Alice最近比较穷(不像集训队陈兴老师是个rich second),所以只能选择做火车从A到B。不过Alice很讨厌坐火车,火车上人比较多,比较拥挤,所以Alice有很严格的要求:火车的相邻两站间的最大距离尽可能的短,这样Alice就可以在停站的时候下车休息一下。当然Alice希望整个旅途比较短。
Input
有多组测试数据。
每组测试数据的第一行有两个整数N,M,A,B(N<=1000, M<=50000, N >=2, A,B<=N),其中N是城市的个数,M是城市间通火车的个数。
A,B是Alice起始的城市与目的地城市,城市的标号从1开始。
接下来的M行每行三个整数u,v,w表示从u到v和从v到u有一条铁路,距离为w, u,v<=N, w<=10000。
Output
对于每组测试数据输出满足Alice要求的从A到B的最短距离。
Sample Input
3 3 1 2
1 2 80
1 3 40
2 3 50
3 3 1 2
1 2 90
1 3 10
2 3 20
4 5 1 4
1 2 8
1 4 9
1 3 10
2 4 7
3 4 8
Sample Output
90
30
15
又是一年校队选拔,又坑在了二分这个题目上面。
这个题目最短路部分不难
关键是想到用二分
之前思路很混乱,我一度也在想要记录每条路的最大边权值,然后对求出来的最短路,优先选择最大边权值最小的那条。。。但是这种思路首先没有落实到二分这个方法上来,其次,我是想边求最短路的时候,边比较此时的最大边权,然后取小的。。非常混乱
记得上次显神就给我讲过最大值最小化问题,我竟然没有转化到这个最短路的题目来
题目条件要使得两个站之间的距离越短越好。。。因此是在站与站的距离越的情况下,来进行最短路。
因此,用二分枚举出最大边权值,(意思就是在该最大权值下,如果边权值大于它,则相当于不通),在枚举出的权值下,进行朴素的迪杰斯特拉最短路(安神用的SPFA,看起来很简洁。膜拜一下。)!
最后坑爹的二分调试了我几个小时(比赛之后)。发现二分真的不是那么好写。。尤其是这道题目,枚举出来的量稍有差池,就输不出正确的值来。
其实后来看了下浙西贫农的代码,忽然觉悟了,不是我的二分没写好,是在判断的时候,应该在边值可达的时候记录下此时的b点最短路值,否则总会发现输出inf
还得练习一下分治专题。
#include <iostream> #include <cstdio> #include <cstring> #define ll long long #define inf 10000000 using namespace std; int d[1005][1005]; int city[1005]; bool vis[1005]; int n,m,a,b; int main() { while (scanf("%d %d %d %d",&n,&m,&a,&b)!=EOF) { int i,j,k; int mmax=0; int mmin=inf; for (i=0; i<=n; i++) { for (j=1; j<=n; j++) d[i][j]=inf; city[i]=inf; } for (j=1; j<=m; j++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); if (d[u][v]>w) d[u][v]=d[v][u]=w; if (mmax<w) mmax=w; if (mmin>w) mmin=w; } city[a]=0; int ans=0; int l=mmin,r=mmax,mid; while (l<r) //二分部分。 { memset(vis,0,sizeof vis); mid=(l+r)/2; for (int i2=1;i2<=n;i2++)//每次二分都要重置最短路 { city[i2]=inf; } city[a]=0; for (i=1;i<=n;i++)//进行朴素的Dijstla { int min=inf,loc; for (j=1;j<=n;j++) { if (vis[j]) continue; if (min>city[j]) { min=city[j]; loc=j; } } vis[loc]=1; for (k=1;k<=n;k++) { if (d[loc][k]>mid) continue; if(vis[k]) continue; if (city[k]>city[loc]+d[loc][k]) city[k]=city[loc]+d[loc][k]; } } if (city[b]>=inf) l=mid+1; else
{
ans=city[b];//应该在这里记录好结果。。。否则下一次二分如果是满足上面那个条件,则最终不是会输出inf r=mid;
} } printf("%d ",ans); } return 0; }