http://codeforces.com/contest/937/problem/D
题意:
给你一个有向图,A和B博弈,从一个S起点开始走,谁不能走了谁就输了。
B睡着了,A替B走。所以B可以很蠢。
如果A不能赢,那么看看A能不能使游戏永远进行下去。
否则只能输了。
POINT:
要赢肯定是有一条路径,走到尾的时候刚好是奇数步。
没有这种路径,就从S开始找能不能进入一个环。
还没有的话,就只能输了。
具体是,VIS[N][2],0代表走到这个点为偶数步,1为奇数步。
所以每个点最多只会被搜到2次。不会TLE。
如果不能赢,用SPFA从s开始搜,看看就没有环。(取所以点的入度最大的那个数,如果更新超过这个数,就有环。不能是n,会超时)。
也可以用dfs染色判环,这个更简单且优秀些。
#include <stdio.h>
#include <iostream>
#include <math.h>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
#define LL long long
const int N = 1e5+55;
vector<int>G[N];
int vis[N][2];
int flag=0;
int ans=0;
stack<int>q;
void dfs(int u,int k)
{
if(vis[u][k]==1){
return;
}
vis[u][k]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
dfs(v,k^1);
if(ans==1){
q.push(u);
return;
}
}
if(G[u].size()==0&&k==1){
q.push(u);
ans=1;
}
}
int n,m;
int col[N];
bool hasloop(int u)
{
col[u]=1;
for(int i=0;i<G[u].size();i++){
int v=G[u][i];
int f=0;
if(col[v]==1) f=1;
else if(col[v]==0) f=hasloop(v);
if(f==1) return f;
}
col[u]=2;
return 0;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
int k,x;scanf("%d",&k);
while(k--){
scanf("%d",&x);
G[i].push_back(x);
}
}
int s;scanf("%d",&s);
dfs(s,0);
if(ans==1){
printf("Win\n");
while(!q.empty()){
printf("%d ",q.top());
q.pop();
}
}else{
if(hasloop(s)) printf("Draw\n");
else printf("Lose\n");
}
}