码迷,mamicode.com
首页 > 其他好文 > 详细

[CCPC2020绵阳E] Escape from the Island - BFS

时间:2021-04-15 12:48:11      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:with   out   反向   cin   ons   define   std   ack   inline   

[CCPC2020绵阳E] Escape from the Island - BFS

Description

给一个图,n个点,m个边。有向。一个人要从起点 S 开始走,要去 n 点。把有向图看成无向图自己选路走,最多走k次,可以不走。走完后,在停的那个点的地方,随机走一个有向边。如果没有出边,就不走。这个人要尽快的走到 n 这个点。问走的时间最长是多少?

Solution

状态 \((p,i)\) 表示走到点 \(p\),以及主动走了 \(i\) 条边

转移有两种

无向:\((p,i) \to (q,i+1), \min\)

有向:\((p,i) \to (q,0), \max\)

考虑从末态开始反向 BFS

前者正常 BFS 即可

后者对 \(p \to q\),在所有 \((q,0)\) 计算完后 \((p,i)\) 再入队,这样即保证了转移的拓扑序,又保证了取的是最大值

注意第二类情况,没有出边的会转移到它自己

#include <bits/stdc++.h>
using namespace std;

#define int long long

const int N = 1e5 + 5;
const int K = 55;

int f[N][K], n, m, k, deg[N], spec[N];
vector<int> g[N], ig[N], pg[N];

int cid = 0;

void solve()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++)
    {
        g[i].clear();
        ig[i].clear();
        pg[i].clear();
    }
    memset(f, 0x3f, sizeof f);
    memset(deg, 0, sizeof deg);
    memset(spec, 0, sizeof spec);
    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        ig[v].push_back(u);
        pg[u].push_back(v);
        g[v].push_back(u);
        g[u].push_back(v);
        deg[u]++;
    }
    queue<pair<int, int>> que;
    memset(f, 0x3f, sizeof f);
    for (int i = 0; i <= k; i++)
    {
        que.push({n, i});
        f[n][i] = 0;
    }
    for (int i = 1; i <= n; i++)
        if (deg[i] == 0)
            spec[i] = 1;
    while (que.size())
    {
        auto [v, i] = que.front();
        que.pop();
        if (i >= 1)
        {
            for (int u : g[v])
            {
                if (f[u][i - 1] > 1e9)
                {
                    que.push({u, i - 1});
                    f[u][i - 1] = f[v][i] + 1;
                }
            }
        }
        if (i == 0)
        {
            for (int u : ig[v])
            {
                deg[u]--;
                if (deg[u] == 0)
                {
                    for (int i = 0; i <= k; i++)
                    {
                        if (f[u][i] > 1e9)
                        {
                            f[u][i] = f[v][0] + 1;
                            que.push({u, i});
                        }
                    }
                }
            }
            if (spec[v])
            {
                for (int i = 1; i <= k; i++)
                {
                    if (f[v][i] > 1e9)
                    {
                        f[v][i] = f[v][0] + 1;
                        que.push({v, i});
                    }
                }
            }
        }
    }
    ++cid;
    cout << "Case #" << cid << ":" << endl;
    // for (int i = 1; i <= n; i++)
    // {
    //     for (int j = 0; j <= k; j++)
    //         cout << f[i][j] << "\t";
    //     cout << endl;
    // }
    for (int i = 1; i <= n; i++)
    {
        int ans = 1e18;
        for (int j = 0; j <= 0; j++)
            ans = min(ans, f[i][j]);
        if (ans > 1e8)
            cout << -1 << endl;
        else
            cout << ans << endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false);

    int t;
    cin >> t;

    while (t--)
    {
        solve();
    }
}

[CCPC2020绵阳E] Escape from the Island - BFS

标签:with   out   反向   cin   ons   define   std   ack   inline   

原文地址:https://www.cnblogs.com/mollnn/p/14661296.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!