D. Sleepy Game
题意:n 个点 , m 条边的有向图。有两个人 A 、B ,芯片开在点 s ,两人轮流移动芯片,A 为先手,最后不能移动者输。 但 B 在睡觉,所以 B 的移动由 A 帮他移。 问 A 是否能赢。如能,输出路径 ;如不能,输出是否可以 平局 或 输。
tags: 每个点两种状态 : 能到这个点且轮到 A 走,能到这个点且轮到B走。
用 pre[i][2] 表示这两种状态的前一个点,dfs 搜索状态,如果能到入度为 0 点,且轮到 B 走,那就赢了。如果不能赢就看是否有环。
// 937 D
#include<bits/stdc++.h>
using namespace std;
#pragma comment(linker, "/STACK:102400000,102400000")
#define rep(i,a,b) for (int i=a; i<=b; ++i)
#define per(i,b,a) for (int i=b; i>=a; --i)
#define mes(a,b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define MP make_pair
#define PB push_back
#define fi first
#define se second
typedef long long ll;
const int N = 200005;
bool flag, vis[N];
int n, m, out[N], pre[N][2];
vector< int > G[N];
void dfs(int u, int now)
{
vis[u] = true;
for(int to : G[u])
{
if(vis[to]) flag = true;
if(pre[to][now^1]==0)
pre[to][now^1]=u, dfs(to, now^1);
}
vis[u] = false;
}
stack< int > Stack;
void solve(int ed, int now) {
Stack.push(ed);
if(pre[ed][now]==INF) return ;
solve(pre[ed][now], now^1);
}
void print_path(int ed) {
puts("Win");
solve(ed, 1);
while(!Stack.empty()) {
printf("%d ", Stack.top());
Stack.pop();
}
puts("");
}
int main()
{
scanf("%d%d", &n, &m);
int ci, to;
rep(i,1,n)
{
scanf("%d", &ci);
rep(j,1,ci) {
scanf("%d", &to);
G[i].PB(to);
++out[i];
}
}
int st; scanf("%d", &st);
pre[st][0] = INF;
dfs(st, 0);
rep(i,1,n)
if(out[i]==0 && pre[i][1]) {
print_path(i); return 0;
}
puts(flag ? "Draw" : "Lose");
return 0;
}