题意:一个N个点的拓扑图,有M个棋子,两个人轮流操作,每次操作可以把一个点的棋子移动到它的一个后继点上(每个点可以放多个棋子),直到不能操作,问先手是否赢。
思路:DFS求每个点的SG值,没有后继的点为必败点。
注意搜索中初始化的问题。
#include<stdio.h> #include<string.h> const int N=1111,M=N*N; struct node{ int v,next; }e[M]; int head[N],cnt,in[N],out[N],n,sg[N],p[N]; void add(int u,int v){ e[cnt].v=v,e[cnt].next=head[u]; head[u]=cnt++; } int SG(int u){ if(!out[u]) return sg[u]=0; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(sg[v]==-1) sg[v]=SG(v); } memset(p,0,sizeof(p)); for(int i=head[u];i!=-1;i=e[i].next){ p[sg[e[i].v]]=1; } for(int i=0;i<n;i++){ if(!p[i]){ return sg[u]=i; } } } int main(){ int m,k,i,u,v; while(~scanf("%d",&n)){ memset(head,-1,sizeof(head)); memset(sg,-1,sizeof(sg)); memset(in,0,sizeof(in)); cnt=0; for(i=0;i<n;i++){ scanf("%d",&k);out[i]=k; while(k--){ scanf("%d",&v); add(i,v);in[v]++; } } for(i=0;i<n;i++){ if(!in[i]){ SG(i); } } while(~scanf("%d",&m)&&m){ int ans=0; while(m--){ scanf("%d",&u); ans^=sg[u]; } if(ans) puts("WIN"); else puts("LOSE"); } } return 0; }