题意:给定一个有向无环图,然后上面的一些结点上面有棋子,每次一个人可以选择一枚棋子走到与它相邻的点,不能走的就输了。然后给出初态,判断胜负。

题解:图上面的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 }