zoukankan      html  css  js  c++  java
  • LG 题解 CF936B Sleepy Game

    题目传送

    更棒的阅读体验?

    Solution

    题意非常的简单,没啥可说的。

    先判断 Win 的情况:

    你考虑用 (f_{u,0/1}) 来表示走到 (u) 这个点走了偶(奇)步这个状态有没有出现过。

    对于边 ((u,v)),显然有转移方程:

    [f_{v,0} |= f_{u,1} ]

    [f_{v,1} |= f_{u,0} ]

    然后你在记录一个出度。

    这样的话,dfs 更新一遍,最后看一看出度为 (0) 的点走了奇步这个状态存在没有。

    题目要求输出路径,这个操作比较平凡,记录一个 (pre) 递归输出即可。

    再考虑判断 Draw 的情况。

    我们要注意的是 Draw 的优先级比 Lose 要高。估计就我一个人没看出来。

    所以在不能走奇步停止的情况下,能进圈就进圈。

    一开始我的想法是用 tarjan 缩点,建出新图,接着从 (s) 所在点 dfs,看看经过的路径有没有环。但是我写挂了。

    考虑另外一种更简单的做法,只从 (s)tarjan,记录下缩的最大环。

    直接根据这个最大环的大小来判断就可以了。

    其他问题看代码。

    Code

    /*
    Work by: Suzt_ilymics
    Problem: 不知名屑题
    Knowledge: 垃圾算法
    Time: O(能过)
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define LL long long
    #define orz cout<<"lkp AK IOI!"<<endl
    
    using namespace std;
    const int MAXN = 2e5+5;
    const int INF = 1e9+7;
    const int mod = 1e9+7;
    
    struct edge {
        int from, to, nxt;
    }e[MAXN << 1];
    int head[MAXN], num_edge = 1;
    
    int n, m, s, cnt = 0, t = 0, Max = 0;
    int od[MAXN];
    int pre[MAXN][2];
    int dfn[MAXN], low[MAXN], siz[MAXN], num[MAXN], stc[MAXN], sc = 0;
    bool f[MAXN][2], vis[MAXN];
    
    int read(){
        int s = 0, f = 0;
        char ch = getchar();
        while(!isdigit(ch))  f |= (ch == '-'), ch = getchar();
        while(isdigit(ch)) s = (s << 1) + (s << 3) + ch - '0' , ch = getchar();
        return f ? -s : s;
    }
    
    void add_edge(int from, int to) { e[++num_edge] = (edge){from, to, head[from]}, head[from] = num_edge; }
    
    void tarjan(int u) {
        dfn[u] = low[u] = ++cnt, vis[u] = true, stc[++sc] = u;
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to;
            if(!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if(vis[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u]) {
            int cnt = 0;
            int pre = stc[sc--]; vis[pre] = false;
            ++cnt;
            while(pre != u) {
                pre = stc[sc--], vis[pre] = false;
                ++cnt;
            }
            Max = max(Max, cnt);
        }
    }
    
    void Dfs(int u) {
        for(int i = head[u]; i; i = e[i].nxt) {
            int v = e[i].to, flag = false;
            if(!f[v][0] && f[u][1]) f[v][0] = true, flag = true, pre[v][0] = u;
            if(!f[v][1] && f[u][0]) f[v][1] = true, flag = true, pre[v][1] = u;
            if(flag) Dfs(v);
        }
    }
    
    void Print(int u, int p) {
        if(pre[u][p]) Print(pre[u][p], p^1);
        printf("%d ", u);
    }
    
    int main()
    {
    	n = read(), m = read();
    	for(int i = 1; i <= n; ++i) {
    	    int k = read();
    	    for(int j = 1, v; j <= k; ++j) {
    	        v = read();
    	        add_edge(i, v);
    	        od[i]++;
            }
        }
        s = read();
        f[s][0] = true;
        Dfs(s);
        bool flag = false;
        for(int i = 1; i <= n; ++i) {
            if(!od[i] && f[i][1]) {
                puts("Win");
                Print(i, 1);
                puts("");
                return 0;
            }
        }
        tarjan(s);
        if(Max > 1) puts("Draw");
        else puts("Lose");
        return 0;
    }
    
    
  • 相关阅读:
    Leetcode 121. Best Time to Buy and Sell Stock
    Leetcode 120. Triangle
    Leetcode 26. Remove Duplicates from Sorted Array
    Leetcode 767. Reorganize String
    Leetcode 6. ZigZag Conversion
    KMP HDU 1686 Oulipo
    多重背包 HDU 2844 Coins
    Line belt 三分嵌套
    三分板子 zoj 3203
    二分板子 poj 3122 pie
  • 原文地址:https://www.cnblogs.com/Silymtics/p/solution-CF936B.html
Copyright © 2011-2022 走看看