题解 Christmas Game
题目大意
给出 \(t\) 个 \(n\) 个点 \(m\) 条边的无向图,每次可以从任意一棵树选择一条边删掉,然后该树不与根(为 \(1\) )联通的部分被删掉。不能操作的人输。问谁有必胜策略。
每棵树都满足:每个环都只会挂在叶子节点上。
\(n\le 100,m\le 500\)
思路
怎么说呢?很厉害的题目吧。
首先考虑一个树的情况,我们设 \(sg(u)\) 表示 \(u\) 子树内的 \(sg\) 函数值,我们可以得到转移式:
\]
\]
这个可以通过打表发现,不过有一种比较巧妙的方法,就是说我们把主链拉出来,那么相当于每一个节点连了一条链,那么,删边就相当于取石子了。
然后考虑拓展到任意图上。这里给出一个结论:
一个环如果大小为偶数,它的顶点产生的贡献为 \(0\),反之为 \(1\)。
相当于环大小为偶数时,把环缩为一个点,否则再连向一个点。
考虑证明,我们发现我们可以通过枚举破掉环上哪条边来求,你发现环大小为偶数时,你破掉之后两条链长度一定一奇一偶,也就是对该环的根(挂的叶子)产生的贡献一定为偶数,所以第一个未出现的正整数一定为 \(1\)。同理,我们可以推出环大小为奇数的情况,这里就不再赘述了。
这里提醒一些细节:
需要考虑重边
需要考虑多个环串在一个顶点的情况
具体见代码就好了。
\(\texttt{Code1}\)
#include <cstdio>
#include <vector>
#include <cstring>
#include <bits/stdc++.h>
using namespace std;
#define Int register int
#define MAXN 105
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
int T,n,m,sg[MAXN],dep[MAXN],vis[MAXN];
int toop,head[MAXN],to[MAXN * 10],nxt[MAXN * 10];
void Add_Edge (int u,int v){
to[++ toop] = v,nxt[toop] = head[u],head[u] = toop;
to[++ toop] = u,nxt[toop] = head[v],head[v] = toop;
}
int dfs (int u,int fa){
bool flag = 0;
dep[u] = dep[fa] + 1,vis[u] = 1;
for (Int i = head[u];i;i = nxt[i]){
int v = to[i];
if (!v) continue;
if (v == fa && !flag){
flag = 1;
continue;
}
if (vis[v]){
sg[v] ^= (dep[u] - dep[v] + 1 & 1);
to[i ^ 1] = 0;
return v;
}
else{
int cur = dfs (v,u);
if (!cur) sg[u] ^= sg[v] + 1;
else if (cur ^ u) return cur;
}
}
return 0;
}
void clear (){
toop = 1,memset (head,0,sizeof (head));
for (Int i = 1;i <= n;++ i) sg[i] = dep[i] = vis[i] = 0;
}
signed main(){
while (~scanf ("%d",&T)){
int ans = 0;
while (T --> 0){
read (n),read (m),clear ();
for (Int i = 1,u,v;i <= m;++ i) read (u),read (v),Add_Edge (u,v);
dfs (1,0),ans ^= sg[1];
}
puts (ans ? "Sally" : "Harry");
}
return 0;
}
\(\texttt{Code2}\)
#include <cstdio>
#include <vector>
using namespace std;
#define Int register int
#define MAXN 105
template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
vector <int> G[MAXN];
int T,n,m,top,sg[MAXN],dep[MAXN],vis[MAXN],sta[MAXN];
void Add_Edge (int u,int v){
G[u].push_back (v),
G[v].push_back (u);
}
void dfs (int u,int fa){
bool flag = 0;
sta[++ top] = u,vis[u] = 1;
for (Int i = 0;i < G[u].size();++ i){
int v = G[u][i];
if (v == fa && !flag){
flag = 1;
continue;
}
if (vis[v] == 1){
int cnt = 1;
while (sta[top] != v){
cnt ++;
vis[sta[top --]] = 0;
}
sg[v] ^= (cnt & 1);
}
else if (vis[v] == -1){
dfs (v,u);
if (vis[v]) sg[u] ^= sg[v] + 1;
}
}
if (vis[u]) -- top;
return ;
}
void clear (){
top = 0;
for (Int i = 1;i <= n;++ i) sg[i] = dep[i] = 0,vis[i] = -1,G[i].clear ();
}
signed main(){
while (~scanf ("%d",&T)){
int ans = 0;
while (T --> 0){
read (n),read (m),clear ();
for (Int i = 1,u,v;i <= m;++ i){
read (u),read (v);
if (u ^ v) Add_Edge (u,v);
}
dfs (1,0),ans ^= sg[1];
}
puts (ans ? "Sally" : "Harry");
}
return 0;
}
题解 Christmas Game的更多相关文章
- 题解 AT4278 【[ABC115A] Christmas Eve Eve Eve】
题目传送门. 分析 根据题目,我们可以发现要求如下: \(d\)的值 输出 \(d=25\) Christmas \(d=24\) Christmas Eve \(d=23\) Christmas E ...
- POJ3160 Father Christmas flymouse[强连通分量 缩点 DP]
Father Christmas flymouse Time Limit: 1000MS Memory Limit: 131072K Total Submissions: 3241 Accep ...
- poj 3013 Big Christmas Tree (最短路径Dijsktra) -- 第一次用优先队列写Dijsktra
http://poj.org/problem?id=3013 Big Christmas Tree Time Limit: 3000MS Memory Limit: 131072K Total S ...
- 【POJ3710】Christmas Game (博弈-树上的删边问题)
[题目] Description Harry and Sally were playing games at Christmas Eve. They drew some Christmas trees ...
- Codeforces:Good Bye 2018(题解)
Good Bye 2018! 题目链接:https://codeforces.com/contest/1091 A. New Year and the Christmas Ornament 题意: 给 ...
- AtCoder Beginner Contest 115 题解
题目链接:https://abc115.contest.atcoder.jp/ A Christmas Eve Eve Eve 题目: Time limit : 2sec / Memory limit ...
- Good Bye 2018题解
Good Bye 2018题解 题解 CF1091A [New Year and the Christmas Ornament] 打完cf都忘记写题解了qwq 题意就是:给你一些黄,蓝,红的球,满足蓝 ...
- Codeforces Round #611 (Div. 3) A-F简要题解
contest链接:https://codeforces.com/contest/1283 A. Minutes Before the New Year 题意:给一个当前时间,输出离第二天差多少分钟 ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
随机推荐
- 记录Mac下使用Charles抓包
抓包 简述 在网络应用如后端系统,app,小程序等的开发过程中,免不了接口可能会报错,但是一般在app中或者小程序中没有便捷的console控制台,而且线上环境也不会开启调试模式,所以想看一下接口的响 ...
- shell脚本 批量添加删除用户
2021-07-26 1.批量添加用户 # 编写脚本 vi add_student_50.sh # 添加用户组 student groupadd student # 添加用户 student1-stu ...
- 理解ASP.NET Core - [03] Dependency Injection
注:本文隶属于<理解ASP.NET Core>系列文章,请查看置顶博客或点击此处查看全文目录 依赖注入 什么是依赖注入 简单说,就是将对象的创建和销毁工作交给DI容器来进行,调用方只需要接 ...
- Python - 文件模式a+读取不了文件
代码 f = open('test/gbk.txt', 'a+', encoding='utf-8') print(f.readline()) 最终的执行结果是输出空,为什么呢? a+模式打开文件指针 ...
- Linux学习笔记--快捷键
桌面 ALT+空格 打开窗口菜单 ALT+F1 聚焦到桌面左侧任务导航栏,可按上下键导航 ALT+F2 运行命令 ALT+F4 关闭窗口 ALT+TAB 切换程序窗口 PRINT 桌面截图 S ...
- [第七篇]——Docker Hello World之Spring Cloud直播商城 b2b2c电子商务技术总结
Docker Hello World Docker 允许你在容器内运行应用程序, 使用 docker run 命令来在容器内运行一个应用程序. 输出Hello world xxx@xxx:~$ do ...
- Python脚本运行出现语法错误:IndentationError:unexpected indent
对于py来说典型错误就是缩进,,烦不胜烦,整理一下解决方法:一个python脚本,本来都运行好好的,然后写了几行代码,而且也都确保每行都对齐了,但是运行的时候,却出现语法错误: Indentation ...
- 洛谷P1160——队列安排(双向链表)
题目描述 一个学校里老师要将班上N个同学排成一列,同学被编号为1-N,他采取如下的方法: 1.先将1号同学安排进队列,这时队列中只有他一个人: 2.2-N号同学依次入列,编号为i的同学入列方式为:老师 ...
- PTA——c++面向对象基础
1.结构不是面向对象的主要特征 2.每个 C++程序中都必须包含有这样一个函数,该函数的函数名为main 3.C++对C语言作了很多改进,下列描述中()使得C语言发生了质变,从面向过程变成了面向对象. ...
- php保留2位小数方法
$num = 10.4567; //第一种:利用round()对浮点数进行四舍五入 echo round($num,2); //10.46 //第二种:利用sprintf格式化字符串 $format_ ...