2018.09.16 loj#10243. 移棋子游戏(博弈论)

传送门
题目中已经给好了sg图,直接在上面跑出sg函数即可。
最后看给定点的sg值异或和是否等于0就判好了。
代码:

#include
#define N 2005
#define M 6005
using namespace std;
int n,m,k,sg[N],first[N],First[N],du[N],cnt=0,ans=0;
bool vis[N];
queue<int>q;
struct edge{int v,next;}e[M],E[M];
inline void add(int u,int v){
    e[++cnt].v=v,e[cnt].next=first[u],first[u]=cnt;
    E[cnt].v=u,E[cnt].next=First[v],First[v]=cnt;
}
inline int max(int a,int b){return a>b?a:b;}
inline int read(){
    int ans=0;
    char ch=getchar();
    while(!isdigit(ch))ch=getchar();
    while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
    return ans;
}
int main(){
    n=read(),m=read(),k=read();
    for(int i=1;i<=m;++i){
        int a=read(),b=read();
        add(a,b),++du[a]; 
    }
    for(int i=1;i<=n;++i)if(!du[i])q.push(i);
    while(!q.empty()){
        int x=q.front(),tmp=0;
        q.pop();
        for(int i=first[x];i;i=e[i].next){
            int v=e[i].v;
            vis[sg[v]]=1,tmp=max(tmp,sg[v]);
        }
        for(int i=0;i<=tmp+1;++i)if(!vis[i]){sg[x]=i;break;}
        for(int i=0;i<=tmp;++i)vis[i]=0;
        for(int i=First[x];i;i=E[i].next){
            int v=E[i].v;
            --du[v];
            if(!du[v])q.push(v);
        }
    }
    for(int i=1;i<=k;++i)ans^=sg[read()];
    printf("%s",ans?"win":"lose");
    return 0;
}

你可能感兴趣的:(#,博弈论)