题目链接:https://loj.ac/problem/10243
解题思路
因为是一张有向无环图,正好对应有向图游戏和模型,可以利用sg函数异或和求解。我们发现,出度为0的点,不能再移动,是P点,所以其sg函数必是0。其它点的sg函数都可以由其儿子节点推出。所以我们对整张图dfs就可以求得所有点的sg函数(图可能要多次dfs)。然后求对应点sg函数异或和,非0则先手必胜,0则先手必败。
AC代码
#include <iostream>
#include <stdio.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2e3+5;
const int maxm=6e3+5;
const int inf=0x3f3f3f3f;
struct node
{
int to,next;
}edge[maxm];
int head[maxn];
int num[maxn];
int sg[maxn];
bool vis[maxn];
int cnt;
int n,m,k;
void add(int x,int y)
{
edge[++cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt;
}
int dfs(int u)
{
bool flag=0;
if(sg[u]!=inf)
return sg[u];
bool vis[maxn];
memset(vis,0,sizeof(vis));
int ma=-1;
for(int i=head[u];i;i=edge[i].next)
{
flag=1;
int v=edge[i].to;
int w=dfs(v);
ma=max(ma,w);
vis[w]=1;
}
if(!flag)
sg[u]=0;
else
{
for(int i=0;i<=ma+1;++i)
if(!vis[i])
{
sg[u]=i;
break;
}
}
return sg[u];
}
int main()
{
scanf("%d%d%d",&n,&m,&k);
memset(sg,inf,sizeof(sg));
while(m--)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=1;i<=n;++i)
{
if(sg[i]==inf)
dfs(i);
}
for(int i=1;i<=k;++i)
scanf("%d",&num[i]);
int ans=0;
for(int i=1;i<=k;++i)
{
ans^=sg[num[i]];
}
if(ans)
puts("win");
else
puts("lose");
return 0;
}