链接:http://codeforces.com/contest/937/problem/D
题意: 现在有一个有向图,有一个起点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
*/