题解 CF813C The Tag Game
Posted qshjydzh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解 CF813C The Tag Game相关的知识,希望对你有一定的参考价值。
先翻译下本题,个人认为翻译不大准确:
A在根节点1上,B在节点t上,现在B开始走,他要尽可能地躲避A通过走到与其相邻节点上。而A要抓B,故他要尽可能去追B。请问,最多几轮后两人会相遇。
分析这道题,可以发现,B的路径只有两种,分别为:1.一直往上走,直到与A相撞。2.往上走,然后到某一个点拐弯,往下走到底。
$ exttt{Part one}$
我们的小B一直往上走,那么小A也一直往下走,他们会在他们两个点组成的链上相遇,至于在哪个点相遇,我们不管他。理性分析发现这条链上除起始点与终点外的点,除了相遇点外,都走了一遍,相遇点走了两边。那么这之间走的步数就是起始点与重点的深度差。
$ exttt{Part two}$
我们的小B经历了一次拐弯,那么我们首先得判断,小B在转弯前,有没有和小A碰到,碰到就不用做了,我们现在考虑未碰到的情况。小B肯定比小A先到底,所以走的步数就是小A到底的距离差的2倍、
讨论结束,我们整理一下我们需要求的东西:
$dep[u] u$点的深度 和 $down[u] u$点往下走,最远能走到哪。
这两个数组,我们都可以用一遍 DFS 遍历求出来。
$dep[u]=dep[fa]+1,down[u]=max(down[u],down[v]+1)$
存图就用一个邻接表存就行了,这就不多说了、
$View Code$
#include<bits/stdc++.h> using namespace std; inline int read() //快读 { int x=0,f=1; char c=getchar(); while(c<‘0‘ || c>‘9‘) {if(c==‘-‘) f=-1;c=getchar();} while(c>=‘0‘ && c<=‘9‘) x=x*10+c-‘0‘,c=getchar(); return x*f; } inline int max(int x,int y) {return x>y?x:y;} //手写max,比较快 const int N=200005; struct Edge { int ed,nxt; }a[N<<1]; //邻接表存图 int tot,h[N],t,n,down[N],dep[N],f[N],ans; inline void add(int x,int y) //加边 { a[++tot].ed=y; a[tot].nxt=h[x]; h[x]=tot; } void dfs(int u,int fa) { f[u]=fa; //处理出没个点的父亲,方便遍历一条链用 dep[u]=dep[fa]+1; for(int i=h[u];i;i=a[i].nxt) { int v=a[i].ed; if(v==fa) continue; dfs(v,u); down[u]=max(down[u],down[v]+1); // 处理该点最多能往下走多少 } } void solve(int u) { if(!u) return; //到头结束 if(dep[t]-dep[u]>=dep[u]-dep[1]) return; //如果在转弯前碰到,结束 ans=max(ans,(dep[u]-dep[1]+down[u])*2); //算出在u转弯的值 solve(f[u]); //往上遍历 } int main() { n=read(),t=read(); for(int i=1;i<n;i++) { int x=read(),y=read(); add(x,y);add(y,x); } dfs(1,0); ans=dep[t]-dep[1]; //小B与小A横冲直撞未拐弯情况 solve(t); printf("%d ",ans); return 0; }
$Thanks for watching$
以上是关于题解 CF813C The Tag Game的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces 813C The Tag Game 贪心
CF833A The Meaningless Game 鎬濈淮