题目链接:Click here~~
题意:
在一个有向无环图上,有若干玩具,每人每次只能将一个玩具移动一步,最后不能移动者输。
解题思路:
很早就听说 sg 函数,今天终于大概看了看,好像也不难写。算法理解的不深,先将就着吧。
算法思想:将 博弈游戏 转成一个 有向无环图,点 u 为能够表述游戏的状态,边 <u,v> 表示状态 u 一步能到达状态 v。
sg[u] = min{x∈N && x!∈{sg[v]} },游戏结束状态 z 出度为0,规定 sg[z] = 0。
最后将 子游戏 的 sg 值异或起来,就是整个游戏的 sg 值了。
#include <vector>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
const int N = 1e4 + 5;
vector<int> g[N];
bool vis[N];
int sg[N];
void dfs(int u)
{
vis[u] = true;
vector<int> num;
for(int i=0;i<(int)g[u].size();i++)
{
int v = g[u][i];
if(!vis[v])
dfs(v);
num.push_back(sg[v]);
}
sort(num.begin(),num.end());
sg[u] = 0;
for(int i=0;i<(int)num.size();i++)
{
if(sg[u] == num[i])
sg[u]++;
else if(sg[u] < num[i])
break;
}
}
int main()
{
int n, ncase = 0;
while(~scanf("%d",&n))
{
memset(vis,false,sizeof(vis));
for(int u=1;u<n;u++)
{
g[u].clear();
int num, v;
scanf("%d",&num);
while(num--)
{
scanf("%d",&v);
g[u].push_back(v);
}
}
g[n].clear();
for(int i=1;i<=n;i++)
if(!vis[i])
dfs(i);
int Q;
scanf("%d",&Q);
printf("Case %d:\n",++ncase);
while(Q--)
{
int num, i, ans = 0;
scanf("%d",&num);
while(num--)
{
scanf("%d",&i);
ans ^= sg[i];
}
puts(ans?"Alice":"Bob");
}
}
return 0;
}