ZOJ 3666 博弈 SG函数
SG函数:
对于任意状态,定义SG(x)=mex(S),其中S是x的后继状态的SG函数值集合,mex(S)表示不再S内的最小非负整数
SG(X)=0当且仅当x为必败态。
解:
构造一个有向无环图(树),SG(x)=mex(SG(y)) y为x的孩子节点。
SG(所有叶子节点)=0
#include <stdio.h> #include <algorithm> #include <string.h> #include <vector> using namespace std; #define MAXN 10005 int n; int sg[MAXN]; vector <int >map[MAXN]; int vis[MAXN]; void dfs(int y) { if (vis[y]) return; int i,j; int x; vector<int> tmp; for (j=0;j<map[y].size();j++) { dfs(map[y][j]); tmp.push_back(sg[map[y][j]]); } sort(tmp.begin(),tmp.end()); x=0; int flag=true; for (i=0;i<tmp.size();i++) if (tmp[i]==x) x++; else { if (tmp[i]>x) { break; } } sg[y]=x; vis[y]=1; } int main() { int i,j,m,x; int dot[MAXN]; int cas=1; while (scanf("%d",&n)!=EOF) { printf("Case %d:\n",cas++); for (i=1;i<=n;i++) map[i].clear(); memset(sg,0,sizeof(sg)); memset(vis,0,sizeof(vis)); for (i=1;i<n;i++) { scanf("%d",&dot[i]); for (j=0;j<dot[i];j++) { scanf("%d",&x); map[i].push_back(x); } } sg[n]=0; for (i=1;i<=n;i++) if (!vis[i]) dfs(i); int q; int p; scanf("%d",&q); for (i=0;i<q;i++) { scanf("%d",&p); int ans=0; for (j=0;j<p;j++) { scanf("%d",&x); ans^=sg[x]; } if (ans==0) printf("Bob\n"); else printf("Alice\n"); } } return 0; }