ural 1750 Tree 2(树的直径 + 倍增)

来源:互联网 发布:centos 6.8 安装pptp 编辑:程序博客网 时间:2024/05/17 08:10
Tree 2
Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u

[Submit]   [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 longusing 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;}


 

0 0
原创粉丝点击