电车_洛谷1346_最短路

56 篇文章 0 订阅

题目描述


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

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

输入格式:


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

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

输出格式:


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

题解


题目一股本子的气息 / 《电车之狼》 什么的
对于默认的路线连边权为0,其他的作1,跑一遍最短路就可以了
注意自环坑人

Code


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <deque>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <sstream>
#include <fstream>
#define debug puts("-----")
#define rep(i, st, ed) for (int i = st; i <= ed; i += 1)
#define drp(i, st, ed) for (int i = st; i >= ed; i -= 1)
#define fill(x, t) memset(x, t, sizeof(x))
#define min(x, y) x<y?x:y
#define max(x, y) x>y?x:y
#define PI (acos(-1.0))
#define EPS (1e-8)
#define INF (1<<30)
#define ll long long
#define db double
#define ld long double
#define N 1001
#define E N * 8 + 1
#define L 255
using namespace std;
struct edge{int x, y, w, next;}e[E];
int inQueue[N], dis[N], tis[N], ls[N];
int edgeCnt;
inline int read(){
    int x = 0, v = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9'){
        if (ch == '-'){
            v = -1;
        }
        ch = getchar();
    }
    while (ch <= '9' && ch >= '0'){
        x = (x << 1) + (x << 3) + ch - '0';
        ch = getchar();
    }
    return x * v;
}
inline int addEdge(int &cnt, const int &x, const int &y, const int &w = 1){
    e[++ cnt] = (edge){x, y, w, ls[x]}; ls[x] = cnt;
    return 0;
}
inline int spfa(const int &st, const int &ed, const int &n){
    fill(inQueue, 0);
    inQueue[st] = 1;
    fill(dis, 63);
    dis[st] = 0;
    fill(tis, 0);
    queue<int>q;
    q.push(st);
    while (!q.empty()){
        int now = q.front(); q.pop();
        if (++ tis[now] >= n){
            return -1;
        }
        for (int i = ls[now]; i; i = e[i].next){
            if (dis[now] + e[i].w < dis[e[i].y]){
                dis[e[i].y] = dis[now] + e[i].w;
                if (!inQueue[e[i].y]){
                    inQueue[e[i].y] = 1;
                    q.push(e[i].y);
                }
            }
        }
        inQueue[now] = 0;
    }
    if (dis[ed] == dis[0]){
        dis[ed] = -1;
    }
    return dis[ed];
}
int main(void){
    int n = read(), st = read(), ed = read();
    edgeCnt = 1;
    rep(i, 1, n){
        int opt = read();
        rep(j, 1, opt){
            int tar = read();
            if (tar != i){
                addEdge(edgeCnt, i, tar, j != 1);
            }
        }
    }
    printf("%d\n", spfa(st, ed, n));
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值