2022牛客暑期多校训练营3 补题

题意:给定一个城市有若干十字路口,右转不需要等红灯,直行、左转和掉头都需要,求起点到终点最少等几次红灯。

思路:可以将每条路径视为点,十字路口处分情况连边,边权赋为0,1,转化为0−1最短路问题,然后直接跑dijkstra

代码:

#include <bits/stdc++.h>
#pragma gcc optimize("O2")
#pragma g++ optimize("O2")
#define int long long
#define endl '\n'
using namespace std;

const int N = 4e6 + 10;

#define pii pair<int, int>
#define mkp make_pair
#define fir first
#define sec second

int n = 0, cnt = 0;
int s1, s2, t1, t2;
vector<pii> g[N];
int dis[N];

struct node{
    int fa, to, res, id;
    const bool operator< (const node &x) const { return res > x.res; }
};

priority_queue<node> pq;

void dijkstra(){
    for(int i = 0; i < 4; i++){
        auto &[v, k] = g[s1][i];
        if(v == s2) pq.emplace(node{s1, s2, 0, k});
    }
    while(pq.size()){
        auto now = pq.top(); pq.pop();
        if(now.to == 0 || dis[now.id] != -1) continue;
        dis[now.id] = now.res;
        for(int i = 0; i < 4; i++){
            auto &[to, k] = g[now.to][i];
            if(to == now.fa) pq.emplace(node{now.to, g[now.to][(i + 1) % 4].fir, now.res, g[now.to][(i + 1) % 4].sec});
            else pq.emplace(node{now.to, g[now.to][(i + 1) % 4].fir, now.res + 1, g[now.to][(i + 1) % 4].sec});
        }
    }
}

void solve(){
    cin >> n;
    memset(dis, -1, sizeof(dis));
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < 4; j++){
            int v; cin >> v;
            g[i].emplace_back(mkp(v, ++cnt));
        }
    }
    cin >> s1 >> s2 >> t1 >> t2;
    dijkstra();
    for(int i = 0; i < 4; i++){
        auto &[to, k] = g[t1][i];
        if(to == t2) cout << dis[k] << endl;
    }
}

signed main(){
    ios_base::sync_with_stdio(false), cin.tie(0);
    int t = 1; //cin >> t;
    while(t--) solve();
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值