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;
}
原文地址:https://www.cnblogs.com/dyzll/p/5812846.html