Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)
记先手移动棋子的树为红树,后手移动棋子的树为蓝树。
首先考虑一个性质,就是如果与当前红色棋子所在的点相连的边中存在一条边,满足这条边的两个端点在蓝树上的距离 \(\ge 3\),那么答案肯定是 \(-1\),因为如果此时红色棋子与蓝色棋子在蓝树上的距离 \(\le 1\),那么先手就可以沿着这条红边将红色棋子移到该边的另一个端点,使红色棋子与蓝色棋子在蓝树上的距离 \(>1\),否则原地不动。如果后手再次将蓝色棋子移到与红色棋子在蓝树上距离为 \(1\) 的位置那先手可以再将棋子沿着这条红边移动 \(1\) 的距离,如此反复进行下去即可。
因此我们考虑先对蓝树进行一遍 DFS 并对每一条红边检验其在蓝树上的距离是否 \(\ge 3\),记 \(ok_x\) 表示是否存在一条与 \(x\) 相连的红边满足其在蓝树上的距离 \(\ge 3\),那么如果先手能够走到一个满足 \(ok_x=1\) 的点,并且下一步还是先手走,那么答案就是 \(-1\)。
那么怎么处理答案不等于 \(-1\) 的情况呢?别急,我们再来找些性质,我们不妨假设现在还不能到达能够无限循环的状态,也就是说所有与当前红色棋子所在点相连的边在蓝树上的距离 \(\le 2\),那么有一个性质是红色棋子肯定不会跨过蓝色棋子,因为如果红色棋子跨过了蓝色棋子,那么此时红色棋子与蓝色棋子距离必然 \(\le 1\),后手必然能在一步之内结束游戏,这显然是先手所不希望看到的。换句话说,任意时刻红色棋子必定在蓝色棋子在蓝树上的子树内,证明可以归纳,读者自证不难。有了这个性质之后我们还能顺带着推出一个性质,那就是记 \(depr_i\) 为 \(i\) 到红树树根的距离,\(depb_i\) 为 \(i\) 到蓝树树根的距离,那么任意时刻如果游戏没有结束,都有 \(depr_x<depb_x\),否则此时此刻红色棋子不在蓝色棋子在蓝树上的子树内,或者两个点位于同一节点上,游戏结束。因此考虑再对红树进行一遍 DFS,如果先手经过 \(depr_x<depb_x\) 的点能够走到 \(ok_x=1\) 的点那么答案就是 \(-1\),否则我们找出红色棋子经过的点中 \(depb\) 的最大值 \(mx\),那么容易证明最优方案是先手将红色棋子移到这个 \(depb\) 最大的点然后原地不动等死,经过的步数为 \(2mx\)。
时间复杂度线性,判断两点在蓝树上距离是否 \(\ge 3\) 不必倍增跳 LCA 求距离,可以直接求出 \(x,y\) 的 \(0,1,2\) 级祖先并判断是否有相同的值。
终于在 NOI 之前把鸽掉的题解全部补完了
const int MAXN=2e5;
int n,x,y;vector<pii> edges_r;
struct graph{
int hd[MAXN+5],to[MAXN*2+5],nxt[MAXN*2+5],ec=0;
void adde(int u,int v){to[++ec]=v;nxt[ec]=hd[u];hd[u]=ec;}
} R,B;
int dep_b[MAXN+5],fa_b[MAXN+5],dep_r[MAXN+5];
void dfs1(int x,int f){
fa_b[x]=f;
for(int e=B.hd[x];e;e=B.nxt[e]){
int y=B.to[e];if(y==f) continue;
dep_b[y]=dep_b[x]+1;dfs1(y,x);
}
}
bool check(int x,int y){
vector<int> fx,fy;
for(int i=0;i<3;i++) fx.pb(x),x=fa_b[x];
for(int i=0;i<3;i++) fy.pb(y),y=fa_b[y];
for(int i=0;i<3;i++) for(int j=0;j+i<3;j++) if(fx[i]==fy[j]) return 0;
return 1;
}
int ans=0,ok[MAXN+5];
void dfs2(int x,int f){
if(dep_r[x]>=dep_b[x]) return;
if(ok[x]) puts("-1"),exit(0);
chkmax(ans,dep_b[x]);
for(int e=R.hd[x];e;e=R.nxt[e]){
int y=R.to[e];if(y==f) continue;
dep_r[y]=dep_r[x]+1;dfs2(y,x);
}
}
int main(){
scanf("%d%d%d",&n,&x,&y);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);edges_r.pb(mp(u,v));
R.adde(u,v);R.adde(v,u);
}
for(int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),B.adde(u,v),B.adde(v,u);
dfs1(y,0);for(pii e:edges_r) if(check(e.fi,e.se)) ok[e.fi]=ok[e.se]=1;
dfs2(x,0);printf("%d\n",ans<<1);
return 0;
}
Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)的更多相关文章
- AtCoder Grand Contest 005
AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...
- AtCoder Grand Contest 005 C - Tree Restoring
题目传送门:https://agc005.contest.atcoder.jp/tasks/agc005_c 题目大意: 给定一个长度为\(N\)的整数序列\(A_i\),问能否构造一个\(N\)个节 ...
- AtCoder Grand Contest 005【A栈模拟,B单调栈】
挖草,AtCoder实在是太吊了~ %%%,目前只A了两题: A题: 就是利用栈模拟一下就好了:S进栈,T的话有S就出栈,然后len减一下就好了: #include <bits/stdc++.h ...
- AtCoder Grand Contest 005题解
传送门 \(A\) 咕咕 const int N=5e5+5; char s[N];int res,n,sum; int main(){ scanf("%s",s+1),res=n ...
- AtCoder Grand Contest 032 A - Limited Insertion( 思维)
Time Limit: 2 sec / Memory Limit: 1024 MB Score : 400400 points Problem Statement Snuke has an empty ...
- AtCoder Regular Contest 094 D Worst Case【思维题】
https://arc094.contest.atcoder.jp/tasks/arc094_b 题意: 在2次超多人的比赛中,你取得的成绩依次为第A名和第B名.一个人的成绩为a和b时,当且仅当ab& ...
- AtCoder Grand Contest 012
AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...
- AtCoder Grand Contest 011
AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...
- AtCoder Grand Contest 031 简要题解
AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...
随机推荐
- 《手把手教你》系列技巧篇(三十三)-java+ selenium自动化测试-单选和多选按钮操作-上篇(详解教程)
1.简介 在实际自动化测试过程中,我们同样也避免不了会遇到单选和多选的测试,特别是调查问卷或者是答题系统中会经常碰到.因此宏哥在这里直接分享和介绍一下,希望小伙伴或者童鞋们在以后工作中遇到可以有所帮助 ...
- 跟着老猫一起来学GO,环境搭建
老猫的GO学习系列博客已经正式发车了,相信大家以前学习一门编程语言的时候也有经验,咱们一般都是从环境开始,在此呢,大家也跟着老猫从最开始的搭建环境开始. GO语言的安装 首先呢,我们开始需要下载GO语 ...
- 【数据结构与算法Python版学习笔记】树——树的遍历 Tree Traversals
遍历方式 前序遍历 在前序遍历中,先访问根节点,然后递归地前序遍历左子树,最后递归地前序遍历右子树. 中序遍历 在中序遍历中,先递归地中序遍历左子树,然后访问根节点,最后递归地中序遍历右子树. 后序遍 ...
- UltraSoft - Beta - Scrum Meeting 11
Date: May 27th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录会议 Liuzh 前端 增加了对重复日程的支持 Kkkk 前端 测试验证前后端 ...
- [no code][scrum meeting] Alpha 3
项目 内容 会议时间 2020-04-07 会议主题 技术规格说明书review 会议时长 1h30min 参会人员 产品经理+后端技术组长(伦泽标)+OCR竞品调研成员(叶开辉)+架构文档负责(黎正 ...
- pyqgis学习细节
关于LIKE通配符:LIKE的意思是模糊匹配,可以和% _搭配,%指的是任意字符,_指的是任一字符.
- numpy.zeros()的作用和实操
numpy.zeros()的作用: 通常是把数组转换成想要的矩阵 numpy.zeros()的使用方法: zeros(shape, dtype=float, order='C') shape:数据尺寸 ...
- 源码解析-Abp vNext丨分布式事件总线DistributedEventBus
前言 上一节咱们讲了LocalEventBus,本节来讲本地事件总线(DistributedEventBus),采用的RabbitMQ进行实现. Volo.Abp.EventBus.RabbitMQ模 ...
- python numpy版本报错: File "*\numpy\__init__.py", line 305, in <module> _win_os_check()
具体代码如下所示: from numpy import * import operator a = random.rand(4, 4) print(a) 具体报错内容如下所示: Traceback ( ...
- 面试官:JavaScript如何实现数组拍平(扁平化)方法?
面试官:JavaScript如何实现数组拍平(扁平化)方法? 1 什么叫数组拍平? 概念很简单,意思是将一个"多维"数组降维,比如: // 原数组是一个"三维" ...