ural 1750 Tree 2(樹的直徑 + 倍增)

Time Limit: 1000MS   Memory Limit: 65536KB   64bit IO Format: %I64d & %I64u

[]   [Go Back]   [Status]  

Description

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 viand 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 Input

input

output

9 101 81 51 42 72 53 65 96 95 48 14 32 49 31 15 23 56 47 3

0123456789

 

 

題意:給出一棵樹,樹上兩點的距離爲兩點路徑上的邊數,有q個詢問,每個詢問u d,要求出與u相距爲d的任意一個結點。

思路:先求樹的直徑,得到直徑上的兩端點,分別以這兩個端點爲根能構造出兩棵新的樹,與任意一個點u距離爲d的結點v可以在其中一棵樹上通過倍增來求出。

 

AC代碼:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
#include <algorithm>
#define ll long long
using namespace std;

const int maxn = 20005;
const int INF = 1e9;

int n, q;
vector<int> G[maxn];
int to[maxn];
int dis[2][maxn], fa[maxn][2], anc[maxn][30][2];
bool vis[maxn];
int bfs(int s, int k){
    queue<int> Q;
    memset(vis, 0, sizeof(vis));
    memset(dis[k], 0, sizeof(dis[k]));
    vis[s] = 1;
    Q.push(s);
    int idx = s, Max = -1;
    while(!Q.empty())
    {
        int u = Q.front();
        Q.pop();
        if(dis[k][u] > Max)
        {
            Max = dis[k][u];
            idx = u;
        }
        for(int i = 0; i < (int) G[u].size(); i++)
        {
            int v = G[u][i];
            if(vis[v]) continue;
            vis[v] = true;
            dis[k][v] = dis[k][u] + 1;
            fa[v][k] = u;
            Q.push(v);
        }
    }
    for(int i = 1; i <= n; i++)
    to[i] = max(to[i], dis[k][i]);
    return idx;
}
void init(){
    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++)
            anc[i][j][k] = -1;
        }
        for(int j = 1; (1 << j) < n; j++)
        for(int i = 1; i <= n; i++)
        if(anc[i][j - 1][k] != -1)
        {
            int a = anc[i][j - 1][k];
            anc[i][j][k] = anc[a][j - 1][k];
        }
    }
}
int query(int k, int u, int d){
    if(d == 0) return u;
    if(d == 1) return anc[u][0][k];
    int log = 1;
    for(; (1 << log) <= d; log++);
    log--;
    for(int i = log; i >= 0; i--)
    {
        if(d >= (1 << i))
        {
            d -= (1 << i);
            u = anc[u][i][k];
        }
        if(d == 0) return u;
    }
    return 0;
}
int main()
{
    int a, b;
    while(~scanf("%d%d", &n, &q))
    {
        for(int i = 1; i <= n; i++) G[i].clear();
        for(int i = 0; i < n - 1; i++)
        {
            scanf("%d%d", &a, &b);
            G[a].push_back(b);
            G[b].push_back(a);
        }
        memset(to, 0, sizeof(to));
        int s = bfs(1, 0);
        int t = bfs(s, 1);
        bfs(t, 0);
        init();
        while(q--)
        {
            scanf("%d%d", &a, &b);
            if(to[a] < b)
            {
                puts("0");
                continue;
            }
            if(dis[0][a] > dis[1][a]) printf("%d\n", query(0, a, b));
            else printf("%d\n", query(1, a, b));
        }
    }
    return 0;
}


 

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