【题目描述】
H城是一个旅游胜地,每年都有成千上万的人前来观光。为方便游客,巴士公司在各个旅游景点及宾馆,饭店等地都设置了巴士站并开通了一些单程巴士线路。每条单程巴士线路从某个巴士站出发,依次途经若干个巴士站,最终到达终点巴士站。一名旅客最近到H城旅游,他很想去S公园游玩,但如果从他所在的饭店没有一路巴士可以直接到达S公园,则他可能要先乘某一路巴士坐几站,再下来换乘同一站台的另一路巴士, 这样换乘几次后到达S公园。现在用整数1,2,…N 给H城的所有的巴士站编号,约定这名旅客所在饭店的巴士站编号为1,S公园巴士站的编号为N。写一个程序,帮助这名旅客寻找一个最优乘车方案,使他在从饭店乘车到S公园的过程中换车的次数最少。
【题目链接】
http://ybt.ssoier.cn:8088/problem_show.php?pid=1377
【算法】
最初建图想的是同一线路相邻点路径权值为0,不同线路+1,发现很不好做,因为不同线路转换情况太多。事实上,若把同一线路先到达的点和后到达的点间权值记为1,表示在后到达的点处更换线路,最后-1是因为最后一步不用换线路已经到了。然后用floyd就过了。
【一点思考】
主要是如何建图,这道题建的图中,点表示的不是单一线路中的车站而是类似现实意义中的车站可以到达经过的任一线路,而边权值为1表示默认会换线路。
【代码】
1 #include <bits/stdc++.h> 2 using namespace std; 3 char s[1100]; 4 int n,m,a; 5 int G[510][510]; 6 int main() 7 { 8 memset(G,0x3f,sizeof(G)); 9 scanf("%d%d ",&m,&n); 10 for(int i=1;i<=m;i++) { 11 vector<int> tmp; 12 gets(s+1); 13 for(int j=1;j<=strlen(s+1);j++) { 14 int cur=0; 15 while(isdigit(s[j])) { 16 cur=cur*10+s[j]-'0'; 17 j++; 18 } 19 tmp.push_back(cur); 20 } 21 for(int j=0;j<tmp.size();j++) { 22 for(int k=j+1;k<tmp.size();k++) { 23 G[tmp[j]][tmp[k]]=1; 24 } 25 } 26 } 27 for(int k=1;k<=n;k++) 28 for(int i=1;i<=n;i++) 29 for(int j=1;j<=n;j++) 30 G[i][j]=min(G[i][j],G[i][k]+G[k][j]); 31 if(G[1][n]>1e7) puts("NO"); 32 else printf("%d ",G[1][n]-1); 33 return 0; 34 }