【题目链接】
http://acm.hust.edu.cn/vjudge/problem/toListProblem.action#OJId=POJ&probNum=3710&title=&source=

【解题报告】
看过贾志豪的论文之后做的一道题。
有几个关键点:

1.如何处理树上的环

tarjan算法判环,然后根据观察所得结论对环缩点。tarjan算法相关内容可以参见我的另一篇题解。



这里写下我的理解。
奇环可以通过去掉一条边变成两条长度相等的链,这是一个必败局面P,它的SG值为0.所以奇环是N局面。
当任意去掉一条边时,一定形成SG值为2k和2m的两条链,他们的异或值一定不为1.
所以由定义知,奇环的SG值为1.
相对的,先手在偶环里去掉一条边,链的长度一定为一奇一偶,,即偶环的所有子局面SG值都不为0,所以,偶环的SG值为0.

之后变成了这样一个模型:

有定理:

叶子节点的SG值为0(P状态),中间节点的SG值为它所有t个叶子节点的SG值加一的异或值:
SG(G)=(SG(G1')+1)^(SG(G2')+1)^ ... ^(SG(Gt')+1)

关于定理的证明可以参见论文。如果一遍不好理解的话可以多看几遍。

最后这道题目就被转化成了经典的NIM游戏。

附上我自己的代码,写的特别丑。轻拍。

【参考资料】
《组合游戏略述——浅谈SG游戏的若干拓展及变形》–贾志豪

《博弈类题目小结》——ACM-cxlove
http://blog.csdn.net/acm_cxlove/article/details/7854526

《POJ 2186 Popular Cows(强连通分量缩点,Tarjan算法)》–gungnir
http://blog.csdn.net/gungnir0711/article/details/49867467

【参考代码】

#include<cstdio>
#include<iostream>
#include<cstring>
#include<stack>
#include<cmath>
using namespace std;
const int maxn=1e4+50;
const int maxm=5e4+50;int head[maxn],LOW[maxn],DFN[maxn],id[maxn],cnt[maxn];
int mp[110][110];
int vis_scc[maxn];
bool mark[maxn];
int  time,scc;
int n,m,k,state;
stack<int>sta;struct edge_T{int to,next;
}edge[maxm];void tarjan( int u, int pre )
{DFN[u]=LOW[u]=++time;sta.push(u);mark[u]=true;for( int k=head[u]; k!=-1; k=edge[k].next ){int v=edge[k].to;if(v==pre)continue;if(!DFN[v]  ) //v还没有时间戳{tarjan(v,u);  //给v打上时间戳LOW[u]=min( LOW[u],LOW[v] );}else if(mark[v] ){LOW[u]=min( LOW[u],DFN[v] );}}if(LOW[u]==DFN[u]){++scc;int v;do{cnt[scc]++;v=sta.top();sta.pop();id[v]=scc;mark[v]=false;}while(u!=v);}
}int get_SG( int u , int pre )
{if(head[u]==-1)return 0;int ans=0;sta.push(u);for( int k=head[u]; k!=-1; k=edge[k].next ){int v=edge[k].to;if(mp[u][v]>1)  //偶数条重边就直接忽略它,不再继续搜索,因为一定是树叶(按照题意),并且SG值为0{if(mp[u][v]&1)mp[u][v]=1;else continue;}if(v==pre)continue;if(  (id[u]==id[v])  ){if( vis_scc[id[u]] )  continue;//已经处理过这个sccif(cnt[id[u]]&1)ans^=1; //奇环else ans^=0;  //偶环vis_scc[id[u]]=true;}else  ans^=(get_SG(v,u)+1);//不是同一个强连通分量,继续搜索}return ans;
}void solve()
{memset(mark,0,sizeof(mark));//tarjan的初始化memset(DFN,0,sizeof(DFN));memset(vis_scc,0,sizeof(vis_scc));memset(cnt,0,sizeof(cnt));time=0; scc=0;while(!sta.empty())sta.pop();for( int i=1; i<=m; i++ ) if(!DFN[i]) tarjan(i,-1);memset(vis_scc,0,sizeof(vis_scc));int t=get_SG(1,-1); //从根节点开始DFS求出SG值state^=t;// cout<<"SG(1)= "<<t<<endl;
}void add_edge(  int L, int R, int O )
{edge[O].to=R;edge[O].next=head[L];head[L]=O;
}int main()
{while(~scanf("%d",&n)){state=0;while(n--) //n个subtree,每个求出根的SG值,然后求异或和{scanf("%d%d",&m,&k);memset(head,-1,sizeof head);memset(mp,0,sizeof(mp));for( int i=1; i<=k; i++ ){int a,b;scanf("%d%d",&a,&b);add_edge(  a,b,i*2-1 );add_edge(  b,a,i*2 );mp[a][b]++;mp[b][a]++;}solve();}//  for(  int i=1; i<=m; i++ )cout<<i<<"   "<<id[i]<<endl;if(state)printf("Sally\n");else printf("Harry\n");}return 0;
}

POJ 3710 Christmas Game(Tarjan+博弈SG函数)相关推荐

  1. 【博弈论】博弈论入门笔记(四类基础博弈+SG函数)

    『博弈论定义』 博弈论又被称为对策论(Game Theory):是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜目标的理论.博弈论是研究互动决策的理论.博弈可以分析自己与对手的 ...

  2. 点分治问题 ----------- P3727 曼哈顿计划E[点分治+博弈SG函数打表找规律]

    题目链接 解题思路: 1.首先对于每个操作我们实际上是一个博弈问题 对于k=1的操作就是很基础的NIM游戏就是找到一条链的异或和为0 对于k=2的操作通过达打表找规律: 如果s是奇数那么偶数的SG函数 ...

  3. NIM博弈+SG函数求解

    ICG 给定一个有向无环图和一个起始顶点上的一枚棋子,两名选手交替的将这枚棋子沿有向边进行移动,无法移动者判负. 这个游戏可以认为是所有 Impartial Combinatorial Games 的 ...

  4. (转)博弈 SG函数

    此文为以下博客做的摘要: https://blog.csdn.net/strangedbly/article/details/51137432 ---------------------------- ...

  5. CodeForces - 850C Arpa and a game with Mojtaba(博弈+sg函数)

    题目链接:点击查看 题目大意:给出n个数,两个人轮流按照规则操作,不能操作的人即为失败,规则很简单,每次找一个质数p的k次幂,记做x=,将数组中所有包含x倍数的数都除以x,必须保证至少有一个数可以除以 ...

  6. 博弈-sg函数的原理和优化(hdu-1536)

    sg函数:sg函数是博弈中的确定一个position性质的一个函数,全称是sprague-grundy. 性质1:对于所有的p-position,都有sg = 0:对于所有的n-position都有s ...

  7. HDU 1846-Brave Game(巴什博弈-SG函数)

    Brave Game Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  8. 【博弈 —— SG函数详解+例题解析】

    前言 如果你对这篇文章可感兴趣,可以点击「[访客必读 - 指引页]一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接. SG函数解析: 博弈游戏的本质是一个有向图游戏,每个状态(局面)是一个图 ...

  9. 数学基础(四)博弈论(巴什博弈~威佐夫博弈(黄金分割率)~尼姆博奕~斐波那契博弈~SG函数模板)

    一.巴什博弈 1.问题模型 只有一堆n个物品,两个人轮流从这堆物品中取物,规定每次至少取一个,最多取m个,最后取光者得胜. 2.解决思路: 当n=m+1时,由于一次最多只能取m个,所以无论先取者拿走多 ...

最新文章

  1. 那些年让你迷惑的阻塞、非阻塞、异步、同步
  2. Python学习笔记(二)
  3. 插入始终是1_C++入门篇(四十四),链表查询与结点插入
  4. qt乱码Could not decode“xxx.cpp“ with “UTF-8“-encoding.Editing not possible问题处理
  5. 基于TableStore构建简易海量Topic消息队列
  6. 《JavaScript权威指南》——JavaScript核心
  7. 经典面试题(49):以下代码将输出的结果是什么?
  8. (转载)Vim入门图解说明
  9. springBoot框架方法上面添加@Transactional注解的使用
  10. CCF201509-3 模板生成系统(100分)
  11. 生产企业ERP流程是什么
  12. 管家婆设计页面用什么做的_管家婆软件主要是用来做什么的?
  13. 【刷题-每天一算法】赛马
  14. 推荐系统(十一)阿里深度兴趣网络(一):DIN模型(Deep Interest Network)
  15. 计算机实训实验报告,审计实务实验报告总结审计实训实验报告计算机审计实验总结...
  16. linux 驱动之PWM蜂鸣器驱动
  17. 你打开的那些网页,大概率是被监控了
  18. 用System中System.setOut()方法修改输出方式
  19. 企查查访问超频怎么办_怎样删除企查查的不良信息
  20. php导入excel 进度条,.NET_进度条在.net导入Excel时的应用实例,本文实例讲述了进度条在.net导 - phpStudy...

热门文章

  1. DataFrame指数权重窗口ewm使用: DataFrame.ewm([com, span, halflife, …])
  2. 题目17 合并两个排序链表
  3. 读书笔记-Android进阶指北-Native Binder原理
  4. CSS像素 物理像素 分辨率 PPI
  5. 基于51单片机实现时间显示及闹钟设置
  6. 06-JavaWEB_JSP
  7. Android常用:手把手教你实现搜索框(含历史搜索记录)
  8. 新版springcloud使用gateway+nacos,服务报错503 Service Unavailable
  9. delphi10.3报E2003 Undeclared identifier: ‘TSuperRttiContext‘
  10. 解决阿里推送sdk 3.0以上初始化报“init cloudchannel failed -- errorcode:10212 -- errorMessage:静默连接进程未初始化”的问题