问题 C: 最少换乘
时间限制: 2 Sec 内存限制: 64 MB提交: 3 解决: 2
[ 提交][ 状态][ 讨论版]
题目描述
欧洲某城是一个著名的旅游胜地,每年都有成千上万的人前来观光旅行。Dr. Kong决定利用暑假好好游览一番。。
年轻人旅游不怕辛苦,不怕劳累,只要费用低就行。但Dr. Kong年过半百,他希望乘坐BUS从住的宾馆到想去游览的景点,期间尽可量地少换乘车。
Dr. Kon买了一张旅游地图。他发现,市政部门为了方便游客,在各个旅游景点及宾馆,饭店等地方都设置了一些公交站并开通了一些单程线路。每条单程线路从某个公交站出发,依次途经若干个站,最终到达终点站。
但遗憾的是,从他住的宾馆所在站出发,有的景点可以直达,有的景点不能直达,则他可能要先乘某路BUS坐上几站,再下来换乘同一站的另一路BUS, 这样须经过几次换乘后才能到达要去的景点。
为了方便,假设对该城的所有公交站用1,2,……,N编号。Dr. Kong所在位置的编号为1,他将要去的景点编号为N。
请你帮助Dr. Kong寻找一个最优乘车方案,从住处到景点,中间换车的次数最少。
输入
第一行: K 表示有多少组测试数据。(2≤k≤8) 接下来对每组测试数据: 第1行: M N 表示有M条单程公交线路,共有N站。(1<=M<=100 1<n<=500) style="box-sizing: border-box;" div="" <="" 每行描述一路公交线路信息,从左至右按运行顺序依次给出了该线路上的所有站号,相邻两个站号之间用一个空格隔开。="" 第2~m+1行:="">
输出
对于每组测试数据,输出一行,如果无法乘坐任何线路从住处到达景点,则输出"N0",否则输出最少换车次数,输出0表示不需换车可以直达。
样例输入
2
3 7
6 7
4 7 3 6
2 1 3 5
2 6
1 3 5
2 6 4 3
样例输出
2 NO对每个单程路线 该路线里面的所有点构成一条边,我们可以把所有点关系构成的边(单向的)的权值赋值为1就像(1 3 5我们可以构成1—3,1—5,3—5的边,,,这样就成了我们常见的最短的问题了)。接下来就是求1到n的最短路了。因为我们多算了第一个线程,它是不计入总换乘数目的,最后的值减去1就行#include<stdio.h> #include<iostream> #include<string.h> #include<algorithm> using namespace std; #define inf 0x3f3f3f int s[1005]; int ma[1005][1005]; int dis[1005]; int vis[1005]; char a[1005]; int main() { int t; scanf("%d",&t); while(t--) { int n,m; int p=0; scanf("%d%d",&n,&m); getchar(); memset(ma,inf,sizeof(ma)); memset(vis,0,sizeof(vis)); memset(dis,inf,sizeof(dis)); for(int i=1;i<=m;i++) { ma[i][i]=0; } for(int i=1;i<=n;i++) { gets(a); p=0; memset(s,0,sizeof(s)); for(int j=0;j<strlen(a);j++) { if(a[j]!=' ') { int sum=0; while(a[j]!=' '&&j<strlen(a)) { sum=sum*10+a[j]-'0'; j++; } s[p++]=sum; } } for(int k=0;k<p;k++) { for(int h=k+1;h<p;h++) { ma[s[k]][s[h]]=1; } } } for(int i=1;i<=m;i++) { dis[i]=ma[1][i]; } vis[1]=1; for(int i=1;i<m;i++) { int minn=inf,u; for(int j=1;j<=m;j++) { if(dis[j]<minn&&!vis[j]) { u=j,minn=dis[j]; } } vis[u]=1; for(int j=1;j<=m;j++) { if(dis[j]>minn+ma[u][j]&&ma[u][j]<inf) { dis[j]=minn+ma[u][j]; } } } if(dis[m]>=inf) printf("NO\n"); else printf("%d\n",dis[m]-1); } }