题意:给定一个有向无环图,然后上面的一些结点上面有棋子,每次一个人可以选择一枚棋子走到与它相邻的点,不能走的就输了。然后给出初态,判断胜负。
题解:图上面的SG博弈,dfs求SG函数,然后依次取异或就行了。
View Code
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 int sg[1005],head[1005],nc; 6 struct Edge 7 { 8 int to,next; 9 }edge[1000000]; 10 void add(int a,int b) 11 { 12 edge[nc].to=b;edge[nc].next=head[a];head[a]=nc++; 13 } 14 bool vis[1005]; 15 void dfs(int now) 16 { 17 vis[now]=true; 18 bool mark[1005]; 19 memset(mark,false,sizeof(mark)); 20 for(int i=head[now];i!=-1;i=edge[i].next) 21 { 22 int t=edge[i].to; 23 if(!vis[t]) 24 dfs(t); 25 mark[sg[t]]=true; 26 } 27 for(int i=0;i<1005;i++) 28 { 29 if(!mark[i]) 30 { 31 sg[now]=i; 32 break; 33 } 34 } 35 } 36 int main() 37 { 38 int n; 39 while(scanf("%d",&n)!=EOF) 40 { 41 memset(head,-1,sizeof(head)); 42 nc=0; 43 for(int i=0;i<n;i++) 44 { 45 int nu; 46 scanf("%d",&nu); 47 for(int j=0;j<nu;j++) 48 { 49 int t; 50 scanf("%d",&t); 51 add(i,t); 52 } 53 } 54 memset(vis,false,sizeof(vis)); 55 for(int i=0;i<n;i++) 56 { 57 if(!vis[i]) 58 dfs(i); 59 } 60 int m; 61 while(scanf("%d",&m),m) 62 { 63 int ss=0; 64 for(int i=0;i<m;i++) 65 { 66 int t; 67 scanf("%d",&t); 68 ss^=sg[t]; 69 } 70 printf("%s\n",ss?"WIN":"LOSE"); 71 } 72 } 73 return 0; 74 }