CodeForces - 813C(最短路径水题)

本文介绍了一个基于树形结构的游戏追逐问题,其中两名玩家Alice和Bob分别采取最优策略以最小化和最大化相遇所需的总步数。文章详细解释了如何通过广度优先搜索算法计算从起点到树上各节点的最短路径,并最终确定最佳策略下所需的最少步数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

The Tag Game 


Alice got tired of playing the tag game by the usual rules so she offered Bob a little modification to it. Now the game should be played on an undirected rooted tree of n vertices. Vertex 1 is the root of the tree.


Alice starts at vertex 1 and Bob starts at vertex x (x ≠ 1). The moves are made in turns, Bob goes first. In one move one can either stay at the current vertex or travel to the neighbouring one.


The game ends when Alice goes to the same vertex where Bob is standing. Alice wants to minimize the total number of moves and Bob wants to maximize it.


You should write a program which will determine how many moves will the game last.


Input
The first line contains two integer numbers n and x (2 ≤ n ≤ 2·105, 2 ≤ x ≤ n).


Each of the next n - 1 lines contains two integer numbers a and b (1 ≤ a, b ≤ n) — edges of the tree. It is guaranteed that the edges form a valid tree.


Output
Print the total number of moves Alice and Bob will make.


Example
Input
4 3
1 2
2 3
2 4
Output
4
Input
5 2
1 2
2 3
3 4
2 5
Output

6


题意:原题有每个案例的分析,但其实用处也不是很大,题目意思很简单,有Alice(以下用A表示)和Bob(以下用B表示),A和B在一棵树上,这棵树是由1~n这n个点构成,不同点之间有路径棵连通,第一行是n和x,后面的n-1行代表哪两个点之间有路径可以连通。现在A在点1上,B在点x上,A要尽可能节省步数来追上B,B要尽可能让A花更多的步数追上他,B可以选择移动一步或者不移动,A每次只能移动一步,和下棋类似B先走,A再走,无论B移动或不移动,都算作一步,要求的是A的步数加上B的步数。

分析:一开始以为要用DP,后来发现B一定是先走到某个位置然后一直不动,所以只要知道B最后停的位置,计算A到那个位置的最短路径即可,其中B要去的那个位置要保证是B先到,所以,要算两种最短路径,一个是A到所有点的最短路径,另一个是B所有点的最短路径,遍历所有点找到满足上述条件的点,并求出让A到满足条件点的最短路径路径中最大值。

代码如下:

#include<iostream>
#include<cstdio>
#include<map>
#include<vector>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N=2e5+10,INF=0x3f3f3f3f;
typedef pair<int,int> P;
int step1[N],step2[N],x;
map<int,vector<int> >m;
void bfs1()//广搜求1到所有点的最短路径
{
    queue<int>q;
    while(!q.empty())
        q.pop();
    q.push(1);
    step1[1]=0;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(vector<int>::iterator it=m[now].begin();it!=m[now].end();it++)
            if(step1[now]+1<step1[(*it)]){
                step1[(*it)]=step1[now]+1;
                q.push((*it));
            }
    }
}
void bfs2()//广搜求x到所有点的最短路径
{
    queue<int>q;
    while(!q.empty())
        q.pop();
    q.push(x);
    step2[x]=0;
    while(!q.empty()){
        int now=q.front();
        q.pop();
        for(vector<int>::iterator it=m[now].begin();it!=m[now].end();it++)
            if(step2[now]+1<step2[(*it)]){
                step2[(*it)]=step2[now]+1;
                q.push((*it));
            }
    }
}
int main()
{
    int n;
    while(~scanf("%d%d",&n,&x)){
        m.clear();
        int a,b;
        for(int i=1;i<n;i++){
            scanf("%d%d",&a,&b);
            m[a].push_back(b);//记录点可走的路径。
            m[b].push_back(a);//因为是互通,所以两点都要记。
        }
        memset(step1,INF,sizeof(step1));//初始化
        memset(step2,INF,sizeof(step2));
        bfs1();bfs2();//调用函数
        int maxl=0;
        for(int i=2;i<=n;i++)
            if(step1[i]>step2[i])//满足是B先到的这个点
                maxl=max(maxl,step1[i]*2);//求最大值
        printf("%d\n",maxl);
    }

    return 0;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值