POJ 3710 Christmas Game [博弈]
题意:略。
思路:这是个删边的博弈游戏。
关于删边游戏的预备知识:http://blog.csdn.net/acm_cxlove/article/details/7854532
学习完预备知识后,这一题就不难了。
首先,用tarjan算法找到每棵树中的双连通分量(即树枝上的多边形),根据Fusion Principle,如果多边形有奇数条边,可以简化为1条边,如果有偶数条边,则可以简化为1个点。代码中使用了vis数组,对于前者,使环内所有的点(包括悬挂点)的vis值为1,后面计算sg值时便不会再进行遍历这些点;对于后者,除了悬挂点和多边形内与悬挂点相邻的一点(相邻点中只取一个)外,多边形内其他点vis为1,这样就相当于将环化为了1条边。另外,题目当中会有重边,根据题意,当出现这种情况时,一定也是出现在树枝的末端。这里直接当作多边形来处理,方法是相同的,如果有偶数条边,化为1个点,奇数条边化为1条边。
然后由Colon Principle,可以计算出整棵树的sg值,之后对于所有的树,就是个Nim游戏了。
更多细节看代码
#include<stdio.h>
#include<string.h>
#include<stack>
#include<algorithm>
#define maxn 105
#define maxp 2000
using namespace std;
int map[maxn][maxn];
bool vis[maxn];
struct node
{
int v, next;
}edge[maxp];
int num_edge, head[maxn];
void init()
{
num_edge = ;
memset(head, -, sizeof(head));
}
void addedge(int a,int b)
{
edge[num_edge].v = b;
edge[num_edge].next = head[a];
head[a] = num_edge++;
}
struct scc
{
int dfn[maxn], low[maxn];
int cnt, scnt;
bool instack[maxn];
stack<int> s;
void init()
{
cnt = scnt = ;
memset(dfn, -, sizeof(dfn));
memset(instack, , sizeof(instack));
}
void tarjan(int u,int father)
{
dfn[u] = low[u] = ++cnt;
s.push(u);
instack[u] = ;
for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].v;
if (v == father)
{
if (map[u][v] > && map[u][v] % == )
vis[u] = ;
continue;
}
if (dfn[v] == -)
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
}
else if (instack[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
scnt = ;
int last;
for (;;)
{
int temv = s.top();
s.pop();
scnt++;
instack[temv] = ;
if ((temv == u) || s.empty())
break;
vis[temv] = ;
last = temv;
}
if (scnt & )
vis[last] = ;
}
return;
}
void solve(int n)
{
init();
for (int i = ; i <= n; i++) if (dfn[i] == -)
tarjan(i, -);
}
};
int getsg(int u,int father)
{
int osum = ;
for (int i = head[u]; i != -; i = edge[i].next)
{
int v = edge[i].v;
if (!vis[v] && v != father)
osum ^= ( + getsg(v, u));
}
return osum;
}
int main()
{
int k, n, m;
scc g;
while (~scanf("%d", &n))
{
int osum = ;
for (int i = ; i <= n; i++)
{
scanf("%d%d", &m, &k);
int a, b;
init();
memset(map, , sizeof(map));
memset(vis, , sizeof(vis));
while (k--)
{
scanf("%d%d", &a, &b);
addedge(a, b);
map[a][b]++;
addedge(b, a);
map[b][a]++;
}
g.solve(m);
osum ^= getsg(, -);
}
if (osum) printf("Sally\n");
else printf("Harry\n");
}
return ;
}
POJ 3710 Christmas Game [博弈]的更多相关文章
- POJ 3710 Christmas Game#经典图SG博弈
http://poj.org/problem?id=3710 (说实话对于Tarjan算法在搞图论的时候就没搞太懂,以后得找时间深入了解) (以下有关无向图删边游戏的资料来自论文贾志豪<组合游戏 ...
- poj 3710 Christmas Game(树上的删边游戏)
Christmas Game Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 1967 Accepted: 613 Des ...
- poj 3710 Christmas Game 博弈论
思路:首先用Tarjan算法找出树中的环,环为奇数变为边,为偶数变为点. 之后用博弈论的知识:某点的SG值等于子节点+1后的异或和. 代码如下: #include<iostream> #i ...
- POJ 3710 Christmas Game
知识储备: 解决办法(奇偶去环): (1) 对于长度为奇数的环,去掉其中任意一个边之后,剩下的 两个链长度同奇偶,抑或之后的 SG 值不可能为奇数,所 以它的 SG 值为 1: (2) 对于长度为 ...
- POJ.3710.Christmas Game(博弈论 树上删边游戏 Multi-SG)
题目链接 \(Description\) 给定n棵"树",每棵"树"的节点可能"挂着"一个环,保证没有环相交,且与树只有一个公共点. 两人轮 ...
- poj 3710 Christmas Game【博弈论+SG】
也就是转换到树形删边游戏,详见 https://wenku.baidu.com/view/25540742a8956bec0975e3a8.html #include<iostream> ...
- POJ 3710 无向图简单环树上删边
结论题,这题关键在于如何转换环,可以用tarjan求出连通分量后再进行标记,也可以DFS直接找到环后把点的SG值变掉就行了 /** @Date : 2017-10-23 19:47:47 * @Fil ...
- Solution -「POJ 3710」Christmas Game
\(\mathcal{Decription}\) Link. 定义一棵圣诞树: 是仙人掌. 不存在两个同一环上的点,度数均 \(\ge 3\). 给出 \(n\) 棵互不相关的圣诞树,双人 ...
- poj 2975 Nim(博弈)
Nim Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 5232 Accepted: 2444 Description N ...
随机推荐
- Python实现对百度云的文件上传
环境准备 python3.6 PyCharm 2017.1.3 Windows环境 框架搭建 selenium3.6 安装方法: pip install selenium 实现步骤: 一.步骤分析 1 ...
- SSM框架 springMVC对静态资源访问的处理
https://my.oschina.net/hnqingping1255/blog/415575 错误信息 [org.springframework.web.servlet.PageNotFound ...
- [ZJOI2011][bzoj2229] 最小割 [最小割树]
题面 传送门 思路 首先我们明确一点:这道题不是让你把$n^2$个最小割跑一遍[废话] 但是最小割过程是必要的,因为最小割并没有别的效率更高的算法(Stoer-Wagner之类的?) 那我们就要尽量找 ...
- shell总结
1. shell脚本的变量赋值 变量赋值语句中的等号左右不能有空格 即 a = 4 //错误 a=4 //正确 2. shell脚步的执行需要权限 chmod +x shell.sh ./shel ...
- 关于python的整形(int)自动转长整形(long)的问题
有时需要访问某个接口,其中传入的整形参数可能比较长就会变成long,这时如果用str()的话‘L’就会被转化到字符串中,导致接口不能识别: 这种情况下应该优先使用json来转译,可以完美保持翻译pyt ...
- 一个javascript继承和使用的例子
继承可以帮助我们实现代码的重用,把对象的属性写入构造函数,对象的方法写入原型后,以下例子演示继承的使用: 示例的css和js在后 父实例,得到一个间隔1s的轮播: <!DOCTYPE html& ...
- pat 团体天梯赛 L2-011. 玩转二叉树
L2-011. 玩转二叉树 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 给定一棵二叉树的中序遍历和前序遍历,请你先将树做个镜 ...
- 洛谷 P1783 海滩防御
题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭.于是,WLP动用了他 ...
- Eclipse与MyEclipse增强代码提示
Eclipse默认是敲入"."之后有代码提示,但假如我们想在敲入类似sys有System的提示,则需要修改一下Eclispe的配置来达到这个效果. 具体配置方法如下: 点Windo ...
- .NET抓取数据范例 抓取页面上所有的链接
原文发布时间为:2009-11-15 -- 来源于本人的百度文章 [由搬家工具导入] .NET抓取数据范例 抓取页面上所有的链接 前台: <%@ Page Language="C#&q ...