Description
Alice想要从城市A出发到城市B,由于Alice最近比较穷(不像集训队陈兴老师是个rich second),所以只能选择做火车从A到B。不过Alice很讨厌坐火车,火车上人比较多,比较拥挤,所以Alice有很严格的要求:火车的相邻两站间的最大距离尽可能的短,这样Alice就可以在停站的时候下车休息一下。当然Alice希望整个旅途比较短。
Input
有多组测试数据。
每组测试数据的第一行有两个整数N,M,A,B(N<=2000, 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
题意:给定n个点,m条路,求一条从起点至终点的路径使得每段路径最短
题解:根据二分的思想,对图中的边从最大值开始进行二分。然后用spfa算法判断在该权值下能否得到路径进行二分区间取段。
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<queue>
#define inf 10000000
using namespace std;
struct lmx{
int v;
int w;
int pre;
};
lmx lm[50005];
int visit[2005];
int des[2005];
int a[2005];
int n,m,s,e,k;
void addedge(int u,int v,int c)
{
lm[k].v=v;
lm[k].w=c;
lm[k].pre=a[u];
a[u]=k++;
}
int spfa(int s,int e,int m)
{
int i;
for(i=1;i<=n;i++) visit[i]=0;
for(i=1;i<=n;i++) des[i]=inf;
queue<int> q;
des[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
visit[u]=0;
for(i=a[u];i!=-1;i=lm[i].pre)
{
if(lm[i].w<=m)
{
if(des[lm[i].v]>des[u]+lm[i].w)
{
des[lm[i].v]=des[u]+lm[i].w;
if(visit[lm[i].v]==0)
{
visit[lm[i].v]=1;
q.push(lm[i].v);
}
}
}
}
}
return des[e]==inf?0:des[e];
}
int main()
{
int d,b,c,i;
while(scanf("%d %d %d %d",&n,&m,&s,&e)!=EOF)
{
memset(a,-1,sizeof(a));
k=0;
for(i=0;i<m;i++)
{
scanf("%d %d %d",&d,&b,&c);
addedge(d,b,c);
addedge(b,d,c);
}
int l=0,r=10001;
int mid;
while(r-l>1)
{
mid=(l+r)/2;
if(spfa(s,e,mid)) r=mid;
else l=mid;
}
printf("%d\n",spfa(s,e,r));
}
return 0;
}