zoukankan      html  css  js  c++  java
  • Codeforces 936B

    题意略。

    思路:

    图论里掺杂了一些动态规划。

    有几个注意点:

    1.dp时状态的设计:因为我们要寻求的是出度为0并且可以从起点走奇数步抵达的点,由于同一个点可以通过多种方式到达。

    并且我们在获得奇数步点的时候,需要偶数步点作为支撑,所以visit[ i ][ j ]表示第i个点能否具备j状态(0、1),也即奇偶数步。

    2.dp采用spfa,也即刷表法。在使用spfa时,最好将点和状态一起打包。

    3.判断有向图是否存在环,可以采用拓扑排序。

    详见代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1e5 + 5;
    
    struct node{
        int v,state;
        node(int v = 0,int state = 0){
            this->v = v;
            this->state = state;
        }
    };
    
    int visit[maxn][2],out[maxn],indegree[maxn],n,m,s;
    bool vis[maxn];
    vector<int> graph[maxn],vs;
    queue<node> que;
    queue<int> topque;
    
    void spfa(){
        memset(visit,0,sizeof(visit));
        visit[s][0] = -1;
        que.push(node(s,0));
        while(que.size()){
            node nd = que.front();
            que.pop();
            int v = nd.v,state = nd.state;
            for(int i = 0;i < graph[v].size();++i){
                int u = graph[v][i];
                if(!visit[u][state ^ 1]){
                    visit[u][state ^ 1] = v;
                    que.push(node(u,state ^ 1));
                }
            }
        }
    }
    bool judcircle(){
        int cnt = 0;
        for(int i = 1;i <= n;++i){
            if(!visit[i][0] && !visit[i][1]) continue;
            if(indegree[i] == 0)
                topque.push(i);
            ++cnt;
        }
        while(topque.size()){
            int v = topque.front();
            topque.pop();
            --cnt;
            for(int i = 0;i < graph[v].size();++i){
                int u = graph[v][i];
                indegree[u] -= 1;
                if(indegree[u] == 0) topque.push(u);
            }
        }
        return cnt > 0;
    }
    void dfs(int cur){
        for(int i = 0;i < graph[cur].size();++i){
            int v = graph[cur][i];
            ++indegree[v];
            if(indegree[v] == 1){
                dfs(v);
            }
        }
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        memset(indegree,0,sizeof(indegree));
        for(int i = 1,to;i <= n;++i){
            scanf("%d",&out[i]);
            for(int j = 0;j < out[i];++j){
                scanf("%d",&to);
                graph[i].push_back(to);
            }
        }
        scanf("%d",&s);
        dfs(s);
        spfa();
        bool circle = judcircle();
        bool jud = false;
        for(int i = 1;i <= n && !jud;++i){
            if(!out[i] && visit[i][1] != 0){
                jud = true;
                printf("Win
    ");
                int now = 1;
                for(int v = i;v != -1;v = visit[v][now],now = now ^ 1){
                    vs.push_back(v);
                }
                for(int j = vs.size() - 1;j >= 0;--j){
                    printf("%d%c",vs[j],j ? ' ' : '
    ');
                }
            }
        }
        if(!jud){
            printf("%s
    ",circle ? "Draw" : "Lose");
        }
        return 0;
    }
    
    /*
    6 6
    1 2
    2 3 4
    1 5
    1 5
    1 6
    0
    3
    */
  • 相关阅读:
    CentOS 6.7 如何启用中文输入法
    10w数组去重,排序,找最多出现次数(精华)
    win10虚拟机搭建Hadoop集群(已完结)
    Linux常用命令
    调用接口显示Required request body is missing
    Git 的使用
    Navicat创建事件,定时更新数据库
    mysql生成UUID
    时间戳与字符串相互转换
    牛客中的错题
  • 原文地址:https://www.cnblogs.com/tiberius/p/9438867.html
Copyright © 2011-2022 走看看