Gangstar(LCA)

题目传送门
在忙碌的ICPC训练后, Vanis和Qiy玩起了警匪游戏。

游戏在一棵具有n个节点的无向树上进行,Qiy作为警察,想要尽早的抓到Vanis。而Vanis作为匪徒,想要尽量逃脱Qiy的追捕。奈何“天网恢恢,疏而不漏”,即使强如Vanis,也只能尽量拖延自己被抓到的时间。

初始时,Qiy处于1号点,Vanis处于x号点。每2秒种,两者可以选择移动1步到相邻的点或留在原地(按上文中提到的策略行动)。当二人在某个时间处于同一顶点时,Qiy便追到了Vanis。Vanis会尽量逃离Qiy的追逐,而Qiy想尽快追到Vanis。作为吃瓜群众的选手们,你们知道Qiy最少要花多少时间才能追捕到Vanis吗?

输入描述:
第一行输入两个正整数n和x,分别表示树的顶点个数以及Vanis初始所在的位置。
接下来n - 1行每行输入两个正整数u和v,表示有一条边连接顶点u和顶点v。

.

  • 保证输入的顶点和边构成一棵无向树。

输出描述:
输出一个整数,表示Qiy追到Vanis所需的时间。
示例1
输入

4 3
1 2
2 3
2 4

输出

4

说明
2s时,vanis停留在3号点,Qiy移动到2号点
4s时,vanis停留在3号点,Qiy移动到3号点,抓捕成功

思路:将顶点1视作树根,逃跑的策略就只有两种,一种是直接往更深的方向跑来拖延时间,另一种是先往深 度小的地方跑之后在被追捕到之前进入到更深的子树中往深处跑拖延时间。所以只需要先通过搜索来计 算所有结点的深度,之后再搜索一次,对于逃跑者能够到达的所有地点,计算其中耗时最大的那个即 可。

ac代码

#include<bits/stdc++.h>
#include<bitset>
#include<unordered_map>
#define pb push_back
#define bp __builtin_popcount
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e6+100;
const int MOD=1e9+7;
int lowbit(int x){return x&-x;}
inline ll dpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t) % MOD; b >>= 1; t = (t*t) % MOD; }return r; }
inline ll fpow(ll a, ll b){ ll r = 1, t = a; while (b){ if (b & 1)r = (r*t); b >>= 1; t = (t*t); }return r; }
int depth[500001], fa[500001][50], lg[500001];
struct node{
    int to,next;
}edge[maxn];
int head[maxn],tol;
void  add(int a,int b)
{
    edge[++tol].to=b;
    edge[tol].next=head[a];
    head[a]=tol;
}
void DFS(int u,int v)//v是u的爸爸!
{
    fa[u][0]=v;depth[u]=depth[v]+1;
    for(int i=1;(1<<i)<=depth[u];i++)
    fa[u][i]=fa[fa[u][i-1]][i-1];

    for(int i=head[u];i;i=edge[i].next)
    {
        node t=edge[i];
        if(t.to==v)//爸爸除外!
        continue;
        DFS(t.to,u);
    }
}
int LCA(int  x,int y)
{
    if(depth[x]<depth[y])swap(x,y);

    while(depth[x]>depth[y])
    {
        x=fa[x][lg[depth[x]-depth[y]]-1];
    }
    if(x==y)return x;
    for(int k=lg[depth[x]];k>=0;k--)
    {
        if(fa[x][k]!=fa[y][k])
        {
          x=fa[x][k];
          y=fa[y][k];
        }
    }
    return fa[x][0];
}
int get(int x,int y)
{
    return depth[x] + depth[y] - 2 * depth[LCA(x, y)];
}
int main()
{
    ios::sync_with_stdio(false);
    int n,x;
    cin>>n>>x;
    for(int i=1;i<n;i++)
    {
        int x,y;
        cin>>x>>y;
        add(x,y);
        add(y,x);
    }
    for(int i = 1; i <= n; ++i)
	lg[i] = lg[i-1] + (1 << lg[i-1] == i);
    DFS(1,0);
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int dis1=get(x,i)*2,dis2=get(1,i)*2;
        if(dis1<dis2)
        {
            ans=max(ans,dis2);
        }
    }
    cout<<ans<<endl;
    system("pause");
    return 0;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章