[CF813C]The Tag Game
题意
给你一棵树,n个点, 以1为根
Alice站在1号点,Bob站在x号点,他们依次移动,Bob先移动,每一次移动他们可以选择呆在原地或者移动到相邻的位置上
当他们移动到同一个点的时候游戏结束,Alice想要游戏快点结束,Bob则相反。
写一个程序算出游戏最终会进行几次。
第一行输入两个整数n,x
接下来n−1行每行两个整数x,y表示一条树边
输出一个整数表示游戏进行的次数。
题解
啊,我原来没有看到Alice在1号点,所以。。。(虽然好像也不会麻烦很多)
考虑最终结果一定是Bob停留在一个点等待Alice来抓他,不然这就不是追及问题而是相遇问题了。
所以问题转换为Bob停留在哪一个点。
首先一个非常明显的条件,这个点一定为叶节点,否则Bob还可以往下走,答案可以更新。
其次,答案需要保证Alice与Bob在之前不能相遇。其实这个条件可以转化为Alice一定要比Bob晚到这个节点,因为Bob的路径要不是直接往下走,要不是先往根节点方向走然后在找到叶节点深度很深的子树走下去,而不论哪一种情况,只要Alice比Bob晚到,就一定能保证二者在之前不会相遇。(实在不懂可以画图解释)
所以只需求出1节点和X节点到所有节点的路径长度,一一判断更新答案即可。
代码
#include<cstdio>
#include<iostream>
#include<cmath>
#include<queue>
#include<vector>
#include<cstring>
#include<algorithm>
#include<map>
#include<set>
#include<stack>
#include<sstream>
#include<string>
using namespace std;
#define inf 200010
vector<int>e[inf];
int n,x;
int d1[inf],d2[inf];//深度
void add(int u,int v)
{
e[u].push_back(v);
e[v].push_back(u);
}
void dfs(int u,int fa,int step,int *d)
{
if(e[u].size()==1&&u!=1)
{
d[u]=step;
}
for(int i=0;i<e[u].size();i++)
{
int v=e[u][i];
if(v!=fa)
{
dfs(v,u,step+1,d);
}
}
}
int main()
{
while(~scanf("%d%d",&n,&x))
{
for(int i=1;i<=n;i++)
{
e[i].clear();
}
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
}
dfs(1,-1,0,d1);//两个点到每个点的距离
dfs(x,-1,0,d2);
int ans=0;
for(int i=1;i<=n;i++)
{
if(d1[i]>d2[i]&&e[i].size()==1)//B先到,且不能再往下
ans=max(ans,d1[i]);
}
printf("%d",ans*2);//乘二因为一人动作算一步
}
return 0;
}

浙公网安备 33010602011771号