• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
L&King
有何不可!
   首页    新随笔    联系   管理    订阅  订阅

HDU 1524 A Chess Game【SG函数】

题意:一个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;
}

 

posted @ 2016-08-13 16:20  L&King  阅读(149)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3