题目链接:
题意:
Alice和Bob玩游戏,Alice追Bob,路径是输入的指定树状图,Bob要尽可能地躲避Alice的追击,结束的标志是Bob和Alice在同一点相遇。
题解:
按照常情,我们在知道有人追我们的时候,我们会尽量往远处跑,那么这道题也不例外,我们要让Bob尽可能往距离他最远的地方跑,不过别光顾着跑,还要记录距离,什么距离?到起始点的距离.
不过,刚开始在做这道题的时候有考虑这样一种情况
A代表的是Alice的初始位置,一开始有想BFS,但是如果是B到与A的交叉点的距离比A到与B的交叉点的距离大的时候,那A与B不就不能到达最左边的最远距离,那该怎么解决呢?
我们可以计算两个人到这个数上面的某一个点的距离,如果说Bob到某一个顶点的距离比Alice到某一个点的距离要大的话,这个点不成立,Bob是不会走滴(Bob要尽量把这个时间最大化)!那我们不考虑这一部分不就行了吗,直接比较的是到某一个节点的时候Alice到这个节点的步数是大于Bob到这一点的步数,这样上面图中的问题就迎刃而解了。
那么我们确实是可以使用广搜来做的,并且根据题目中给出的例子,就算Bob到最远的角落里,这一点还是要加上的,那么我们只需求Alice到达最远处的距离就行了,然后乘以2.
#include <iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<cstring>
using namespace std;
const int maxn=2e5+5;
vector<int>mpp[maxn];//建立vector
int num1[maxn],num2[maxn];//分别代表Alice, Bob距离各自初始点的距离
int indexx[maxn];//判断是否走过某一点
int n,x;
void Bfs(int beginn,int *num)
{
queue<int>q;
memset(num,0,sizeof(num));
memset(indexx,0,sizeof(indexx));//标记是否走过
num[beginn]=0;//距离
indexx[beginn]=1;
q.push(beginn);
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=0;i<mpp[t].size();++i)
{
int l=mpp[t][i];
if(indexx[l]) continue;
indexx[l]=1;
num[l]=num[t]+1;
q.push(l);
}
}
}
int main()
{
while(~scanf("%d%d",&n,&x))//n-1组数据,Bob初始点
{
int a,b;
for(int i=0;i<maxn;++i)
mpp[i].clear();
for(int i=1;i<n;++i)
{
cin>>a>>b;
mpp[a].push_back(b);
mpp[b].push_back(a);
}
Bfs(1,num1);
Bfs(x,num2);
int num_puts=0;
for(int i=1;i<=n;++i)
{
if(num1[i]>num2[i])
num_puts=max(num_puts,num1[i]);
}
printf("%d\n",num_puts*2);
}
return 0;
}