1377:最优乘车(travel)

1377:最优乘车(travel)

时间限制: 1000 ms ??? ??? 内存限制: 65536 KB
提交数: 12437 ??? 通过数: 3001
【题目描述】
H城是一个旅游胜地,每年都有成千上万的人前来观光。为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴士线路。每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站。

一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路巴士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园。

现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名旅客所在饭店的巴士站编号为1,S公园巴士站的编号为N。

写一个程序,帮助这名旅客寻找一个最优乘车方案,使他在从饭店乘车到S公园的过程中换车的次数最少。

【输入】
第一行有两个数字M和N(1<=M<=100 1<N<=500),表示开通了M条单程巴士线路,总共有N个车站。从第二行到第M行依次给出了第1条到第M条巴士线路的信息。其中第i+1行给出的是第i条巴士线路的信息,从左至右按运行顺序依次给出了该线路上的所有站号相邻两个站号之间用一个空格隔开。

【输出】
只有一行。如果无法乘巴士从饭店到达S公园,则输出"N0",否则输出你的程序所找到的最少换车次数,换车次数为0表示不需换车即可到达。

【输入样例】
3 7
6 7
4 7 3 6
2 1 3 5
【输出样例】
2
思路

1优先考虑Dijkstra,接下来考虑如何设置边以达到正确结果。

2.如样例1–3,3–6(换乘一次),6–7(换乘两次);像样例一样,2–1换乘一次1–3换乘一次,3—5换乘一次,同时2—3或2–5也同样换乘一次显然 不能按样例给出把每个点之间边权设置成一 ,所以我们可以考虑加边方法。

3我们以二点无力在他与1,3,5,之间加一些边使其能直接到达1,3,5那么它到1,3,5,换乘次数均为1,若把图上所以点均按二点处理,并把边权设为1,那么这个图就能求出正确换乘。

#include<bits/stdc++.h>
using namespace std;
string str;
int mxv=0x3f3f3f3f,sp,arr[10007],cnt=1,ans=0;
int m,n,d[1007],f[1007],e[1007][1007],js;
void dijkdtra(int sid){
	d[sid]=0;f[sid]=true;
	for(int i=1;i<=n-1;i++){
		int minn=mxv;
		for(int j=1;j<=n;j++){
			if(!f[j]&&d[j]<minn){
				minn=d[j];
				sp=j;
			}
		}
		f[sp]=true;
		for(int j=1;j<=n;j++){
			if(!f[j]){
				d[j]=min(d[j],d[sp]+e[sp][j]);
			}
		}		
	}
}
int main(){
	memset(d,0x3f,sizeof(d));
	memset(e,0x3f,sizeof(e));
	cin>>m>>n;
	for(int i=1;i<=m+1;i++){
		getline(cin,str);
		for(int j=0;j<str.size();j++){
			if('0'<=str[j]&&str[j]<='9'){
				int jl=str[j]-'0';
				ans=ans*10+jl;
			}else{
				arr[cnt]=ans;
				ans=0;
				cnt++;
			}
		}
		arr[cnt]=ans;
		for(int i=1;i<=cnt;i++){
			for(int j=i+1;j<=cnt;j++){
				e[arr[i]][arr[j]]=1;
			}
		}
		memset(arr,0,sizeof(arr));
		cnt=1;
		ans=0;
	}
	for(int i=1;i<=n;i++){
		d[i]=e[1][i];
	} 
	dijkdtra(1);
	if(d[n]==mxv){
		cout<<"NO";
	}else{
		cout<<d[n]-1;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值