版权声明:转载注明下出处就行了。 https://blog.csdn.net/LJD201724114126/article/details/83780442
题目链接:poj 2425
题意:题目会给出一个有向无环图,对于某个棋子,可以将它移动到其后继棋子的任意一个位置,一个位置可以放多个棋子。
给出n个点,从0到n-1,接着n行,每行开始有Xi,代表第i个点后继连接点有Xi个,分别是......。
紧接着有多组询问,每组询问的M代表有哪几个可走的棋子(M为0时询问结束),问:谁能获胜?先走获胜输出 WIN。
题解:就是个SG函数。
参考博客:https://blog.csdn.net/i1020/article/details/79395763
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std;
const int maxn=1010;
vector<int> que[maxn];
int SG[maxn];
int dfs(int x)
{
if(SG[x]!=-1) return SG[x];
bool vis[maxn]; ///这里不应放在函数外,因为每次递归调用都需用这个标记函数
///假设放在函数外,会产生混乱,注意下这个大坑
memset(vis,0,sizeof(vis));
for(int i=0;i<que[x].size();i++)
{
dfs(que[x][i]);
vis[SG[que[x][i]]]=1;
}
for(int i=0;;i++)
{
if(!vis[i]){
SG[x]=i;break;
}
}
return SG[x];
}
int main()
{
int n;
int item,num;
while(~scanf("%d",&n))
{
for(int i=0;i<n;i++)
{
que[i].clear();
scanf("%d",&num);
while(num--)
{
scanf("%d",&item);
que[i].push_back(item);
}
}
memset(SG,-1,sizeof(SG));
for(int i=0;i<n;i++)
SG[i]=dfs(i);
while(~scanf("%d",&num)&&num)
{
int sum=0;
while(num--)
{
scanf("%d",&item);
sum^=SG[item];
}
if(sum) printf("WIN\n");
else printf("LOSE\n");
}
}
return 0;
}