COJ1307 City Tour 最短路+二分

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的最短距离。

思路:一开始以为是求只要从A点出发,找从该点出发最小值。后来讲评时,再仔细研究了下题目,发现其要求的是相邻两站的最大距离尽可能短,也是说所有边都要小于一个值(最大距离),且要求从A点到B点要有解。这样,题目也就不难了。。总之,理解题意还是比较重要的。
#include<stdio.h>  
#include<string.h>  
#include<queue>  
#include<algorithm>  
using namespace std;  
#define maxn 2010
#define maxm 100010
typedef pair<int,int> pii;
priority_queue<pii,vector<pii>,greater<pii> >p;
int first[maxn],next[maxm],n,m,s,t,tot,ans,d[maxn]; 
struct node  
{  
    int v,w;  
}edge[maxm]; 
bool dj(int mid)  
{  
	memset(d,0x3f,sizeof(d));  
	d[s]=0;
	p.push(make_pair(0,s));
	while(!p.empty())
	{
		pii cur=p.top();
		p.pop();
		if(cur.first>d[cur.second])continue;
		for(int i=first[cur.second];i!=-1;i=next[i])
		{
			if(edge[i].w<=mid)
				if(d[edge[i].v]>d[cur.second]+edge[i].w)
				{
					d[edge[i].v]=d[cur.second]+edge[i].w;
					p.push(make_pair(d[edge[i].v],edge[i].v));
				}
		}
	}
	if(d[t]!=0x3f3f3f3f)return true;
	else return false;

}  
void add_edge(int u,int v,int w)
{
	edge[tot].v=v;edge[tot].w=w;
	next[tot]=first[u];first[u]=tot++;
}
int main()  
{  
    while(~scanf("%d%d%d%d",&n,&m,&s,&t))  
    {  
        int i,j,k,u,v,w;  
        memset(first,-1,sizeof(first));  
       
        tot=0;  
        for(i=1;i<=m;i++)  
        {  
            scanf("%d%d%d",&u,&v,&w);  
            add_edge(u,v,w);
			add_edge(v,u,w);
        }  
		int front=0,rear=10001,mid;
		while(front<rear)
		{
			mid=front+(rear-front)/2;
			if(dj(mid)){rear=mid;ans=d[t];}
			else front=mid+1;
		}
        printf("%d\n",ans);  
        
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值