http://poj.org/problem?id=3710

(说实话对于Tarjan算法在搞图论的时候就没搞太懂,以后得找时间深入了解)

(以下有关无向图删边游戏的资料来自论文贾志豪《组合游戏略述——浅谈SG游戏的若干拓展及变形》)

首先,对于无向图的删边游戏有如下定理性质:

1.(Fushion Principle定理)我们可对无向图做如下改动:将图中的任意一个偶环缩成一个新点,任意一个奇环缩成一个新点加一个新边;所有连到原先环上的边全部改为与新点相连;这样的改动不影响图的SG值。

2.(1)对于长度为奇数的环,去掉其中任意一个边之后,剩下的两个链长度同奇偶,抑或之后的SG值不可能为奇数,所以它的SG值为1;

    (2)对于长度为偶数的环,去掉其中任意一个边之后,剩下的两个链长度异奇偶,抑或之后的SG值不可能为0,所以它的SG值为0;

3.对于树的删边游戏,有如下定理:

          叶子节点的SG值为0;中间节点的SG值为它的所有子节点的SG值+1后的异或和。

所以对于这道题,用连通图的Tarjan算法找出环,然后删环,变成简单树,再进行Nim计算即可。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std; vector<int> edge[105]; //邻接表
int belong[105][105]; //存放边的数量
int low[105],dfn[105];
int s[105],top; //堆栈
bool instack[105];
bool vis[105]; //用于标记不需要的点 void tarjan(int u,int pre,int depth)
{
low[u]=dfn[u]=depth;//depth是时间戳,即level
s[top++]=u;
instack[u]=true;
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
if(v==pre&&belong[u][v]>1) //判断重边
{
if(belong[u][v]%2==0)//偶环
vis[u]=true;
continue;
}
if(!dfn[v])
{
tarjan(v,u,depth+1);
low[u]=min(low[u],low[v]);
}
else if(v!=pre&&instack[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
int cnt=1;
top--;
while(s[top]!=u)
{
vis[s[top--]]=true;
cnt++;
}
if(cnt&&(cnt&1)) //若节点为奇数,则保留两个点加一条边
vis[s[top+1]]=false;
}
} int getsg(int u,int pre)
{
int res=0;
for(int i=0;i<edge[u].size();i++)
{
int v=edge[u][i];
res^=(getsg(v,u)+1);
//叶子节点sg=0,其所有子节点的sg+1后进行异或
}
return res;
} void init(int m)
{
for(int i=1;i<=m;i++)
edge[i].clear();
memset(belong,0,sizeof(belong));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(instack,0,sizeof(instack));
memset(vis,0,sizeof(vis));
top=0;
} void add_edge(int u,int v)
{
belong[u][v]++;
belong[v][u]++;
edge[u].push_back(v);
edge[v].push_back(u);
} int main()
{
int n,m,k;
while(~scanf("%d",&n))
{
int res=0;
while(n--)
{
scanf("%d%d",&m,&k);
init(m); while(k--)
{
int u,v;
scanf("%d%d",&u,&v);
add_edge(u,v);
}
tarjan(1,-1,1);
res^=getsg(1,-1);
}
if(res)
printf("Sally\n");
else printf("Harry\n");
}
return 0;
}

最新文章

  1. Android 手机卫士8--删除通话记录
  2. angularjs 遇到的问题汇总
  3. linux入门级常用命令
  4. 【HDU 4445】Crazy Tank(暴力)
  5. Python PEP8规范
  6. gulp顺序执行任务
  7. Eclipse集成javap查看字节码
  8. MVC 4 中编译时,让View 也弹出异常
  9. 修改Myecclipse servlet/jsp的默认模板
  10. Android Activity管理类
  11. -_-#【Canvas】回弹
  12. IT第七天 - 类及其属性、方法的理解,断点调试初识,代码优化总结,编程逻辑培养
  13. python成长之路——第四天
  14. centos7.0 vsftp配置
  15. 什么是javascript中的静态方法?一个例子让你懂~!
  16. win10 uwp 读写XML
  17. vue-cli+webpack打包配置
  18. 使用 Parallels Destop 最小化安装 centOS 操作系统
  19. VS2017 + QT5 + C++开发环境搭建和计算器Demo测试
  20. 2015-2016 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2015)

热门文章

  1. ES 6 : 函数的扩展
  2. 关于一条定制长按Power键弹出Dialog的需求
  3. 【Python】32. Longest Valid Parentheses
  4. 第9章 创建Web数据库
  5. php学习笔记——CSS缓存问题
  6. 为什么switch...case语句比if...else执行效率高
  7. linuxlab下虚拟板与主机通信
  8. 通过Windows常见性能计数器分析服务器性能瓶颈
  9. PHP不使用递归的无限级分类
  10. nyoj 523 双向广搜