codeforces1472G Moving to the Capital(spfa变形)

传送门
题解:首先看清题意后,发现这道题和cf1473E挺像的,首先算出 d d d 值,跑个 b f s bfs bfs ,然后接着考虑 a n s [ i ] [ 0 / 1 ] ans[i][0/1] ans[i][0/1] 表示起点为 i i i 的路径中其中没有 2 2 2 操作和有 1 1 1 2 2 2 操作的路径中所能到达的最小的 d d d 值,所以更新其实还是简单的。考虑一条边为 i − > j i->j i>j,那么
i f ( d [ i ] < d [ j ] )   a n s [ i ] [ 0 ] = m i n ( a n s [ i ] [ 0 ] , a n s [ j ] [ 0 ] ) , a n s [ i ] [ 1 ] = m i n ( a n s [ i ] [ 1 ] , a n s [ j ] [ 1 ] ) e l s e   a n s [ i ] [ 1 ] = m i n ( a n s [ i ] [ 1 ] , a n s [ j ] [ 0 ] ) if(d[i]<d[j])\ ans[i][0]=min(ans[i][0],ans[j][0]),ans[i][1]=min(ans[i][1],ans[j][1])\\ else\ ans[i][1]=min(ans[i][1],ans[j][0])\\ if(d[i]<d[j]) ans[i][0]=min(ans[i][0],ans[j][0]),ans[i][1]=min(ans[i][1],ans[j][1])else ans[i][1]=min(ans[i][1],ans[j][0])
然后考虑建反图,之后把初值全部压进 s e t set set 中,然后开始不断地 s p f a spfa spfa 直到没有更新。
代码中 a n s [ i ] [ 0 ] ans[i][0] ans[i][0] 表示为 d [ i ] . f i r s t d[i].first d[i].first a n s [ i ] [ 1 ] ans[i][1] ans[i][1] 表示为 d [ i ] . s e c o n d d[i].second d[i].second .

#include <bits/stdc++.h>
using namespace std;
const int inf = 0x3f3f3f3f;
int main()
{
    
    
    int T;
    cin >> T;
    while (T--) {
    
    
        int n, m;
        cin >> n >> m;
        vector<int> g[n], rg[n];
        for (int i = 0, u, v; i < m; i++) {
    
    
            cin >> u >> v;
            u--; v--;
            g[u].emplace_back(v);
            rg[v].emplace_back(u);
        }
        vector<int> dis(n);
        vector<pair<int, int>> d(n, {
    
    inf, inf});
        queue<pair<int, int>> q;
        d[0].first = 0;
        dis[0] = 0;
        set<pair<int, pair<int, int>>> s;
        q.push({
    
    0, 0});
        s.insert({
    
    0, {
    
    0, 0}});
        while (!q.empty()) {
    
    
            int u = q.front().first, w = q.front().second;
            q.pop();
            for (auto x : g[u]) {
    
    
                if (x == 0 || d[x].first != inf) {
    
    
                    continue;
                } else {
    
    
                    d[x].first = w + 1;
                    dis[x] = d[x].first;
                    q.push({
    
    x, d[x].first});
                    s.insert({
    
    d[x].first, {
    
    x, 0}});
                }
            }
        }
        while (!s.empty()) {
    
    
            auto [u, f] = s.begin()->second;
            s.erase(s.begin());
            for (auto v : rg[u]) {
    
    
                if (f == 0) {
    
    
                    if (dis[v] < dis[u]) {
    
    
                        if (d[v].first > d[u].first) {
    
    
                            auto it = s.find({
    
    d[v].first, {
    
    v, 0}});
                            if (it != s.end()){
    
    
                                s.erase(it);
                            }
                            d[v].first = d[u].first;
                            s.insert({
    
    d[v].first, {
    
    v, 0}});
                        }
                    }else {
    
    
                        if (d[v].second > d[u].first) {
    
    
                            auto it = s.find({
    
    d[v].second, {
    
    v, 1}});
                            if (it != s.end()){
    
    
                                s.erase(it);
                            }
                            d[v].second = d[u].first;
                            s.insert({
    
    d[v].second, {
    
    v, 1}});
                        }
                    }
                } else {
    
    
                    if (dis[v] < dis[u]) {
    
    
                        if (d[v].second > d[u].second) {
    
    
                            auto it = s.find({
    
    d[v].second, {
    
    v, 1}});
                            if (it != s.end()){
    
    
                                s.erase(it);
                            }
                            d[v].second = d[u].second;
                            s.insert({
    
    d[v].second, {
    
    v, 1}});
                        }
                    }
                }
            }
        }
        for (auto x : d) {
    
    
            cout << min(x.first, x.second) << " ";
        }
        cout << endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/112792753