codeforces 937d D. Sleepy Game
阿新 • • 發佈:2018-12-12
題意: 現在有一個有向圖,有一個起點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 */