URAL 1752 Tree 2 树的直径与倍增

来源:互联网 发布:电池健康度软件 编辑:程序博客网 时间:2024/06/01 14:39

假设树的直径的两个端点为p0,p1。如果对于一次询问(v,k)存在点q满足要求,那么q必然在v到p0或v到p1的路径上。

剩下的就是在树上寻找p了。倍增就好了。

#include <algorithm>#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <queue>#include <cmath>#include <stack>#include <map>#define LL long long#define ULL unsigned long long#define INF 0x3f3f3f3fusing namespace std;const int MAXN = 20010;const int MAXM = 15;struct N{    int v,next;}edge[2*MAXN];int head[MAXN];int Top;void Link(int u,int v){    edge[Top].v = v;    edge[Top].next = head[u];    head[u] = Top++;}int pa[2][MAXN][MAXM];int dep[2][MAXN];void InitDepFa(int s,int lay,int pre = -1,int d = 0){    dep[lay][s] = d;    pa[lay][s][0] = pre;    for(int  p = head[s];p != -1; p = edge[p].next)    {        if(edge[p].v != pre)            InitDepFa(edge[p].v,lay,s,d+1);    }}void InitPa(int n,int lay){    int i,j;    for(j = 1;j < MAXM; ++j)    {            for(i = 1;i <= n; ++i)            {                if(pa[lay][i][j-1] != -1)                    pa[lay][i][j] = pa[lay][pa[lay][i][j-1]][j-1];                else                    pa[lay][i][j] = -1;            }    }}int QueryKthPoint(int u,int k,int lay){    for(int i = MAXM-1;i >= 0 && k; --i)    {        if(k >= (1<<i))        u = pa[lay][u][i],k -= (1<<i);    }    return u;}queue<int> q;bool mark[MAXN];int bfs(int s){    memset(mark,false,sizeof(mark));    mark[s] = true;    q.push(s);    while(q.empty() == false)    {        s = q.front();        q.pop();        for(int p = head[s] ;p != -1; p = edge[p].next)            if(mark[edge[p].v] == false)            q.push(edge[p].v),mark[s] = true;    }    return s;}int main(){    int i,u,v,n,m,a,k;    while(scanf("%d %d",&n,&m) != EOF)    {        memset(head,-1,sizeof(head));        Top = 0;        for(i = 1;i < n; ++i)        {            scanf("%d %d",&u,&v);            Link(u,v);            Link(v,u);        }        u = bfs(v = bfs(1));        InitDepFa(u,0);        InitPa(n,0);        InitDepFa(v,1);        InitPa(n,1);        while(m--)        {            scanf("%d %d",&a,&k);            if(dep[0][a] >=k)                printf("%d\n",QueryKthPoint(a,k,0));            else if(dep[1][a] >= k)                printf("%d\n",QueryKthPoint(a,k,1));            else                printf("0\n");        }    }    return 0;}

0 0