2021-08-02

09:11:29

链接

https://www.luogu.com.cn/problem/P1346

 

题目描述

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

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

输入格式

第一行有 3 个整数 N,A,B(2N100,1A,BN),分别表示路口的数量,和电车的起点,终点。

接下来有 N 行,每行的开头有一个数字 Ki0KiN1),表示这个路口与 Ki 条轨道相连,接下来有 Ki 个数字表示每条轨道所通向的路口,开关默认指向第一个数字表示的轨道。

输出格式

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

输入输出样例

输入 #1
3 2 1
2 2 3
2 3 1
2 1 2
输出 #1
0

 

分析:

这是一道图论题,但是我们只看题干的话好像只能找到图中的点,找不到图中的边和权重,题目描述从起点到终点所要做的最少的切换开关的次数。但是每个点(路口)都有不同的状态,这样有点抽象,我们先将样例讲一下

样例建图如下

 

 

 

那么点已经找到了,边和边的权重怎么找呢?

我们看到,每个路口指向的第一个路口为默认状态,就是说,如果你从路口1到路口2的话,如果路口2是路口1的默认状态,那么就不需要切换开关,总切换数没变,就说明该边的权重为0,如果我们从路口1走到路口3的话,但是路口1的默认状态是指向路口2的,那么我们就需要切换一次开关,这使得总切换数+1。所以,我们找到了权重。(边就类似从路口1指向路口2的边)。

 

 

 所以我们在输入的时候,将所有路口指向的第一个路口设为默认,权值为0,指向其他路口的权值全部为1。

至此,我们已经完全构造好了一个图

样例建图如下

 

 

 

完整代码:

 

#include<iostream>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=105;
int g[N][N];
int n,from,to;

void Floyd(){
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(g[i][j]>g[i][k]+g[k][j])
                    g[i][j]=g[i][k]+g[k][j];
            }
        }
    }
}

int main()
{
    cin>>n>>from>>to;
    memset(g,0x3f,sizeof g);
    for(int i=1;i<=n;i++)g[i][i]=0;
    for(int i=1;i<=n;i++)
    {
        int k;
        cin>>k;
        for(int j=1;j<=k;j++){
            int a;
            cin>>a;
            if(j==1){
                g[i][a]=0;
            }
            else g[i][a]=1;
        }
    }
    Floyd();
    if(g[from][to]==INF)cout<<-1<<endl;
    else cout<<g[from][to]<<endl;
    return 0;
}

 2021-08-02

09:41:36

  

 

posted on 2021-08-02 09:39  Dragon昴  阅读(112)  评论(0)    收藏  举报