• ural1752 Tree 2


    Tree 2

    Time limit: 1.0 second
    Memory limit: 64 MB
    Consider a tree consisting of n vertices. A distance between two vertices is the minimal number of edges in a path connecting them. Given a vertex vi and distance di find a vertex ui such that distance between vi and ui equals to di.

    Input

    The first line contains the number of vertices n (1 ≤ n ≤ 20000) and the number of queries q(1 ≤ q ≤ 50000). Each of the following n − 1 lines describes an edge and contains the numbers of vertices connected by this edge. Vertices are numbered from 1 to n. The next q lines describe the queries. Each query is described by a line containing two numbers vi (1 ≤ vi ≤ n) and di(0 ≤ di ≤ n).

    Output

    You should output q lines. The i-th line should contain a vertex number ui, the answer to the i-th query. If there are several possible answers, output any of them. If there are no required vertices, output 0 instead.

    Sample

    inputoutput
    9 10
    1 8
    1 5
    1 4
    2 7
    2 5
    3 6
    5 9
    6 9
    5 4
    8 1
    4 3
    2 4
    9 3
    1 1
    5 2
    3 5
    6 4
    7 3
    
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    

    分析:参考自http://www.lai18.com/content/7044719.html;

       首先找到树的直径的两个端点,因为如果在端点到询问点之间没有答案,那么肯定没有答案;

       然后根据端点建树,若存在答案,则需要求出距离询问点为d的点,而这个点就在树根与询问点之间且距询问点为d;

       然后关键的地方就是对每个点,保留距离为2^k的祖先,存放在祖先数组中,这样就可以利用倍增求出答案了;

    代码:

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <climits>
    #include <cstring>
    #include <string>
    #include <set>
    #include <map>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <list>
    #define rep(i,m,n) for(i=m;i<=n;i++)
    #define rsp(it,s) for(set<int>::iterator it=s.begin();it!=s.end();it++)
    #define mod 1000000000
    #define inf 0x3f3f3f3f
    #define vi vector<int>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define ll long long
    #define pi acos(-1.0)
    #define pii pair<int,int>
    #define Lson L, mid, rt<<1
    #define Rson mid+1, R, rt<<1|1
    const int maxn=2e4+10;
    using namespace std;
    ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);}
    ll qpow(ll p,ll q){ll f=1;while(q){if(q&1)f=f*p;p=p*p;q>>=1;}return f;}
    int n,m,k,t,s,q,dis[maxn][2],fa[maxn][2],anc[maxn][30][2],ma,id;
    vi a[maxn];
    void dfs(int now,int pre)
    {
        for(int x:a[now])
        {
            if(x!=pre)
            {
                dis[x][0]=dis[now][0]+1;
                if(dis[x][0]>ma)ma=dis[x][0],id=x;
                dfs(x,now);
            }
        }
    }
    void dfs1(int now,int pre,int p)
    {
        for(int x:a[now])
        {
            if(x!=pre)
            {
                dis[x][p]=dis[now][p]+1;
                fa[x][p]=now;
                dfs1(x,now,p);
            }
        }
    }
    void init()
    {
        memset(anc,-1,sizeof anc);
        for(int k=0;k<2;k++)
        {
            for(int i=1;i<=n;i++)
            {
                anc[i][0][k]=fa[i][k];
            }
            for(int j=1;(1<<j)<n;j++)
            {
                for(int i=1;i<=n;i++)
                {
                    if(anc[i][j-1][k]!=-1)
                    {
                        anc[i][j][k]=anc[anc[i][j-1][k]][j-1][k];
                    }
                }
            }
        }
    }
    int query(int p,int now,int d)
    {
        for(int i=29;i>=0;i--)
        {
            if(d>=(1LL<<i))
            {
                d-=(1LL<<i);
                now=anc[now][i][p];
            }
            if(d==0)return now;
        }
    }
    int main()
    {
        int i,j;
        id=1;
        scanf("%d%d",&n,&q);
        rep(i,1,n-1)scanf("%d%d",&j,&k),a[j].pb(k),a[k].pb(j);
        dfs(1,-1);s=id;
        ma=0;id=1;
        memset(dis,0,sizeof dis);
        dfs(s,-1);t=id;
        memset(dis,0,sizeof dis);
        dfs1(s,-1,0);dfs1(t,-1,1);
        init();
        while(q--)
        {
            int u,d;
            scanf("%d%d",&u,&d);
            if(dis[u][0]>=d)printf("%d
    ",query(0,u,d));
            else if(dis[u][1]>=d)printf("%d
    ",query(1,u,d));
            else puts("0");
        }
        //system("Pause");
        return 0;
    }
  • 相关阅读:
    vs2015 停 在 update kb2999226 一直不动
    修复vs2012出现 “无法找到包源”的错误
    forward 和redirect的区别
    软件测试分类
    centos7安装HTTPS协议
    php抓取网页特定div区块及图片,从简单入手
    nginx报 File not found 错误
    关于端口
    调试技巧:让断点停在for循环中的 i 为某个值得时候
    an AC a day keeps the WA away ~
  • 原文地址:https://www.cnblogs.com/dyzll/p/5812846.html
Copyright © 2020-2023  润新知