标签:read code 不用 inline tchar str 邻接 div 需要
先翻译下本题,个人认为翻译不大准确:
A在根节点1上,B在节点t上,现在B开始走,他要尽可能地躲避A通过走到与其相邻节点上。而A要抓B,故他要尽可能去追B。请问,最多几轮后两人会相遇。
分析这道题,可以发现,B的路径只有两种,分别为:1.一直往上走,直到与A相撞。2.往上走,然后到某一个点拐弯,往下走到底。
$\texttt{Part one}$
我们的小B一直往上走,那么小A也一直往下走,他们会在他们两个点组成的链上相遇,至于在哪个点相遇,我们不管他。理性分析发现这条链上除起始点与终点外的点,除了相遇点外,都走了一遍,相遇点走了两边。那么这之间走的步数就是起始点与重点的深度差。
$\texttt{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\n",ans);
return 0;
}
$Thanks\ for\ watching$
标签:read code 不用 inline tchar str 邻接 div 需要
原文地址:https://www.cnblogs.com/qshjydzh/p/12399179.html