1752. Tree 2 (数据结构)

找出树直径的两个端点,找出所有点到这两个点的距离。

对每一个询问。查看被询问点到两个端点距离为k的点,如果存在就输出。


#include <iostream>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <list>
#include <deque>
#include <string>

#define LL long long
#define DB double
#define SI(a) scanf("%d",&a)
#define SD(a) scanf("%lf",&a)
#define SS(a) scanf("%s",a)
#define SF scanf
#define PF printf
#define MM(a,v) memset(a,v,sizeof(a))
#define REP(i,a,b) for(int (i)=(a);(i)<(b);(i)++)
#define REPD(i,a,b) for(int (i)=(a);(i)>(b);(i)--)
#define N 20009
#define INF 0x3f3f3f3f
#define EPS 1e-8
#define bug puts("bug")
using namespace std;
int dp1[N][16],dp2[N][16];
vector<int> L[N];
int n,q;
queue<int> que;
int dis[N];
int visit[N];
int fin(int k)
{
    MM(dis,INF);
    int ret;
    que.push(k);
    dis[k] = 0;
    while(!que.empty())
    {
        int e = que.front();que.pop();
        ret = e;
        REP(i,0,(int)L[e].size())
        {
            int to = L[e][i];
            if(dis[to]==INF)
            {
                dis[to] = dis[e]+1;
                que.push(to);
            }
        }
    }return ret;
}
void dfs(int k,int dp[][16])
{
    REP(i,0,(int)L[k].size())
    {
        int to = L[k][i];
        if(visit[to]) continue;
        visit[to] = 1;
        dp[to][0] = k;
        REP(j,1,16)
        {
            dp[to][j] = dp[dp[to][j-1]][j-1];
            if(dp[to][j]==0) break;
        }
        dfs(to,dp);
    }
}
void ini()
{
    int rt1 = fin(1);
    int rt2 = fin(rt1);
    MM(visit,0);
    visit[rt1] = 1;
    dfs(rt1,dp1);
    MM(visit,0);
    visit[rt2] = 1;
    dfs(rt2,dp2);
}
int solve(int k,int d)
{
    if(d==0) return k;
    int ret = k;
    REPD(i,30,-1)
    {
        if(d&(1<<i))
        ret = dp1[ret][i];
        if(ret==0) break;
    }
    if(ret) return ret;
    ret = k;
    REPD(i,30,-1)
    {
        if(d&(1<<i))
        ret = dp2[ret][i];
        if(ret==0) break;
    }
    return ret;
}
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    #endif
    SI(n);SI(q);
    int a,b;
    REP(i,1,n)
    {
        SI(a);SI(b);
        L[a].push_back(b);
        L[b].push_back(a);
    }
    ini();
    while(q--)
    {
        SI(a);SI(b);
        PF("%d\n",solve(a,b));
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值