[CF936B] Sleepy Game - DFS,BFS

[CF936B] Sleepy Game - DFS,BFS

Description

有向图上指定一个起点。若存在一条到叶子距离为奇数的路径(注意这里的路径不一定是最短路径),则必胜。若不存在,但是可以到达一个回路,则可以平局。上述两种都不能达到,则失败。

Solution

这里实际上是两个问题

  1. 是否存在一条到叶子距离为奇数的路径
  2. 是否能走到一个环

对于问题 1,我们用图 dp 的方法做,即建立分层图然后 BFS,具体地,图分为奇层和偶层,起点在偶层上,连边永远在相邻层中连

对于问题 2,DFS 一遍,始终标记栈中结点,如果能走回栈中结点,那么就有环

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

#define int long long

const int N = 2e5 + 5;

int s;
int n, m;
vector<int> g[N];

int vis[N];

void dfs(int p)
{
    vis[p] = 1;
    for (int q : g[p])
    {
        if (vis[q] == 0)
        {
            dfs(q);
        }
        else
        {
            cout << "Draw" << endl;
            exit(0);
        }
    }
    vis[p] = 0;
}

namespace solution
{
    vector<int> g[N];
    int vis[N], from[N];

    void main()
    {
        for (int i = 1; i <= n; i++)
        {
            for (int q : (::g[i]))
            {
                g[i].push_back(q + n);
                g[i + n].push_back(q);
            }
        }

        queue<int> que;
        que.push(s);
        vis[s] = 1;
        while (que.size())
        {
            int p = que.front();
            que.pop();
            for (int q : g[p])
            {
                if (!vis[q])
                {
                    vis[q] = 1;
                    from[q] = p;
                    que.push(q);
                }
            }
        }
        for (int i = n + 1; i <= 2 * n; i++)
        {
            if (g[i].size() == 0 && vis[i])
            {
                cout << "Win" << endl;
                vector<int> ans;
                int p = i;
                while (p)
                    ans.push_back(p), p = from[p];
                while (ans.size())
                {
                    int t = ans.back();
                    ans.pop_back();
                    if (t > n)
                        t -= n;
                    cout << t << " ";
                }
                exit(0);
            }
        }
    }
} // namespace solution

signed main()
{
    ios::sync_with_stdio(false);
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        int t;
        cin >> t;
        while (t--)
        {
            int x;
            cin >> x;
            g[i].push_back(x);
        }
    }
    cin >> s;
    solution::main();
    dfs(s);
    cout << "Lose" << endl;
}
上一篇:E - Magical Ornament 题解(图论+状压dp)


下一篇:剑指 Offer 32 - I. 从上到下打印二叉树