1. 程式人生 > >codeforces 937d D. Sleepy Game

codeforces 937d D. Sleepy Game

題意: 現在有一個有向圖,有一個起點S,S有一個小球,小A和小B輪流將小球挪到下一個可能挪到的位置,不能挪的人輸,因為題目並沒有說兩個人足夠聰明,所以只需要找到一個距離S為奇數並且是出度為0 的點就可以了。如果小A不能贏得話,就是儘量平局,如果小A能走進一個環,那麼就可以平局。

所以這個題就是 首先找到距離S為奇數並且出度為0 的點,沒有的話找到一個環,沒有的話,就是lose。對於第一個我們可以dp dp[ i ][ j ]表示走到i點  為奇偶的是否可能。

程式碼:

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N =1e5+5;
const int M =2e5+5;

struct Edge
{
    int v;
    int nxt;
}edge[M*2];
int tot;
int head[N];

int n,m,S;
int outde[N];
int vis[N];
int dp[N][2];
int f;

void add(int u,int v)
{
    edge[tot].v=v; edge[tot].nxt=head[u]; head[u]=tot++;
}

void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}

void dfs(int u,int fa,int flag)
{
    if(dp[u][flag]) return ;
    dp[u][flag]=fa;
    for(int i=head[u];i!=-1;i=edge[i].nxt){
        int v=edge[i].v;
        if(v==fa) continue;
        dfs(v,u,1-flag);
    }
}


void dfs1(int u,int flag)
{
    //cout<<"u "<<u<<" step "<<step<<endl;

    for(int i=head[u];i!=-1;i=edge[i].nxt)
    {
        int v=edge[i].v;
        if(vis[v]) f=1;
        if(dp[v][1-flag]) continue;
        dp[v][1-flag]=1;
        vis[v]=1;
        dfs1(v,1-flag);
        vis[v]=0;
    }
}

int dfs1(int u)
{
    if(vis[u]==2) return 1;
    vis[u]=2;
    for(int i=head[u];i!=-1;i=edge[i].nxt)
    {
        int v=edge[i].v;
        if(vis[v]==0){
            if(dfs1(v)) return 1;
        }
        else if(vis[v]==2) return 1;
    }
    vis[u]=1;
    return 0;
}

int main()
{
    int u,v;
    scanf("%d %d",&n,&m);
    init();
    for(int i=1;i<=n;i++){
        scanf("%d",&outde[i]);
        for(int j=1;j<=outde[i];j++){
            scanf("%d",&v);
            add(i,v);
        }
    }
    scanf("%d",&S);
    dfs(S,S,0);
    f=0;
    for(int i=1;i<=n;i++){
        if(outde[i]==0&&dp[i][1]){
            u=i;
            f=1;
            break;
        }
    }

    if(f)
    {
        vector<int >ans;
        int cnt=0;
        while(u!=S||cnt%2==0)
        {
            ans.push_back(u);
            ++cnt;
            if(cnt%2==1) u=dp[u][1];
            else u=dp[u][0];
        }
        ans.push_back(S);
        printf("Win\n");
        for(int i=ans.size()-1;i>=0;i--){
            printf("%d ",ans[i]);
        }
        return 0;
    }

    f=0;
    f=dfs1(S);
    if(f) printf("Draw\n");
    else printf("Lose\n");

    return 0;
}

/*

4 4
2 3 2
1 4
1 4
0
1

*/