题解 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 鎬濈淮

题解「CF1373B」01 Game

CF1349C Orac and Game of Life题解

CF1105D Kilani and the Game

题解CF#172(Div. 1) C.Game on Tree