[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;
}

  

posted @ 2020-12-24 19:29  EDawn  阅读(125)  评论(0)    收藏  举报