洛谷P1346 电车(最短路径问题)

洛谷P1346 电车


原题地址



一、题目内容

在一个神奇的小镇上有着一个特别的电车网络,它由一些路口和轨道组成,每个路口都连接着若干个轨道,每个轨道都通向一个路口(不排除有的观光轨道转一圈后返回路口的可能)。在每个路口,都有一个开关决定着出去的轨道,每个开关都有一个默认的状态,每辆电车行驶到路口之后,只能从开关所指向的轨道出去,如果电车司机想走另一个轨道,他就必须下车切换开关的状态。

为了行驶向目标地点,电车司机不得不经常下车来切换开关,于是,他们想请你写一个程序,计算一辆从路口 A 到路口 B 最少需要下车切换几次开关。

输入格式
第一行有 3 个整数 N,A,B(2≤N≤100,1≤A,B≤N),分别表示路口的数量,和电车的起点,终点。
接下来有 N 行,每行的开头有一个数字 Ki(0≤Ki≤N−1),表示这个路口与 Ki 条轨道相连,接下来有 Ki 个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。

输出格式
输出文件只有一个数字,表示从 A 到 B 所需的最少的切换开关次数,若无法从 A 前往 B,输出 −1。

输入输出样例
输入 #1

3 2 1
2 2 3
2 3 1
2 1 2

输出 #1

0

二、解题思路

这道题用djikstra也行,用floyd也行。这道题相当于从起点走到终点,求最小总路程。其中对于每个点,如果走到的点是这个点连出的第一条边,总路程不加;如果是其它边,就加一。所以,在建边前,所有边都初始化为正无穷。因为数据不是很大,所以用floyd就行了,我习惯性用我最喜欢的暴力解法(不用怎么动脑)

代码如下:

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100+10;
const int inf=1e+8;//定义无穷大
int g[maxn][maxn];//地图
int n,m,k,a,b;
int main()
{
    
    
    cin>>n>>a>>b;//路口数,起点和终点
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
        {
    
    
            g[i][j]=inf;//初始化地图
            g[i][i]=0;//自己踩过的地方不用按开关
        } 
    for(int i=1;i<=n;i++)
    {
    
    
        cin>>k;//每个路口与k条轨道相连
        for(int j=1;j<=k;j++)
        {
    
    
            cin>>m;//k个表示每条轨道所通向的路口
            if(j==1)//是否是第一条边
                g[i][m]=0;
            else 
                g[i][m]=1;//需要按开关
        }
    }
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                g[i][j]=min(g[i][j],g[i][k]+g[k][j]);//通过中间点k求得是从i-j近还是从i-k-j近,从而求得a到b的最短路径
    if(g[a][b]==inf)//没找到
        cout<<"-1";
    else 
        cout<<g[a][b];
    return 0;
}

三、注意事项

这道题是最短路问题,dijksra,floyd和spfa都可以解的经典题目。单单那floyd来说,这道题首先要找到核心算法g[i][j]=min(g[i][j],g[i][k]+g[k][j]),然后想好建图方式和判断方法。还有一个我们要注意的是我们建的每一条边都只是单向边,不要用g[i][j]=g[j][i]
蒟蒻写得很烂而且有参考一些大佬的讲解,说的不好的地方请批评指正。

猜你喜欢

转载自blog.csdn.net/jotaro07/article/details/110298231
今日推荐