Codeforces-Gadget Hackwrench-LCA最近公共祖先

来源:互联网 发布:淘宝潮男鞋店铺推荐 编辑:程序博客网 时间:2024/05/01 01:17

题目链接:http://codeforces.com/gym/100685/problem/G


Gadget Hackwrench
time limit per test
2 seconds
memory limit per test
64 megabytes
input
standard input
output
standard output

Chip 'n' Dale rescue rangers! But observant viewers know that help is usually required by Chip and Dale themselves. Today you are in the role of cunning Gadget Hackwrench.

So, Chip and Dale are again in the paws of Fat Cat. He doesn't like rodents much and therefore prepared a treacherous test. He is going to put them to a labyrinth and see if they can escape from it. The labyrinth is actually built as a tree where each edge has fixed direction (by definition tree is a connected unoriented graph without cycles).

Gadget has intercepted a talk between Fat Cat and his henchmen about future tests. For each test round she knows the exact location where Chip and Dale are to be put by Fat Cat and the location of an exit. Gadget wants to compute whether they will be able to find an exit for each test.

Input

The first line of input contains an integer N (1 ≤ N ≤ 105) — the number of vertices in a graph.

On the next N - 1 lines of input directed arcs of the tree are given. On the (i + 1)th line integer numbers ai and bi are given (1 ≤ ai, bi ≤ N) denoting an arc from vertex ai to vertex bi. It is guaranteed that arcs a1, a2, ..., an - 1 without orientation form a tree.

Then a string with integer number M (1 ≤ M ≤ 105) is given — the number of queries to process. Next M lines describe queries:(n + 1 + i)th line contain integers xi and yi (1 ≤ xi, yi ≤ N).

Output

For each query please output a separate line containing 'Yes' (without quotes) if graph contains a path between xi and yi, or 'No' (without quotes) in other case.

Examples
input
41 23 14 161 23 22 34 24 32 1
output
YesYesNoYesNoNo


一道LCA的题,记录每个节点到根节点需要经过几个方向向下的边(用flag数组来存)。然后最后判断是否合法只需要判断,这两个点到他们的最近公共祖先是否合法。比如LCA(a,b)为a,b的最近公共祖先,这两个点分别为a,b;那么就是判断flag[a]-flag[LCA(a,b)]是否等于0以及flag[b]-flag[LCA(A,B)]是否等于他们的深度差。LCA(a,b)为a,b的最近公共祖先。

代码如下。

//RMQst表来做LCA//树的节点是从1到n开始排列。//fat[i][j]表示第i个节点的第2^j个祖先是谁//2^20 = 1 048 576#include<cstdio>#include<cstring>#include<algorithm>#include<queue>#include<vector>#define maxn 100010using namespace std;int flag[maxn];int fat[maxn][30];int len[maxn];int n;struct node{    int val,dir;};vector<node>v[maxn];void dfs(int now,int father){    fat[now][0]=father;    len[now]=len[father]+1;    for(int i=0;i<v[now].size();i++)    {        if(v[now][i].val==father)            continue;        if(v[now][i].dir)        flag[v[now][i].val]=flag[now]+1;        else flag[v[now][i].val]=flag[now];        dfs(v[now][i].val,now);    }}void init(){    memset(len,0,sizeof(len));    memset(fat,0,sizeof(fat));    memset(flag,0,sizeof(flag));    int i,j;    dfs(1,0);    for(int i=1;i<=19;i++)    {        for(int j=1;j<=n;j++)        {            fat[j][i]=fat[fat[j][i-1]][i-1];        }    }}int lca(int x,int y){    if(len[x]>len[y])        swap(x,y);    //保证x的深度较小    //下面只需要将y拉到x的位置就好    for(int i=19;i>=0;i--)    {       if(len[fat[y][i]]>=len[x])        y=fat[y][i];    }    //现在x,y已经在同一高度    //可以求LCA了      if(x==y)    {        return x;//这是x和y其中一个是另一个的祖宗    }    for(int i=19;i>=0;i--)    {        if(fat[y][i]!=fat[x][i])        {            y=fat[y][i];            x=fat[x][i];        }    }    return fat[x][0];}int main(){    int uu,vv;    int m;    while(scanf("%d",&n)!=EOF)    {    for(int i=0;i<maxn;i++)    {        v[i].clear();    }        for(int i=1;i<n;i++)        {            scanf("%d%d",&uu,&vv);            node vvv,uuu;            vvv.val=vv;            uuu.val=uu;            uuu.dir=1;            vvv.dir=0;            v[uu].push_back(vvv);            v[vv].push_back(uuu);        }        init();     scanf("%d",&m);     for(int i=1;i<=m;i++)     {         flag[0]=0;         scanf("%d%d",&uu,&vv);         int root=lca(uu,vv);         int fuck,cao;         fuck=flag[uu]-flag[root];         cao=flag[vv]-flag[root];         if(cao==0&&fuck==len[uu]-len[root])            flag[0]=1;         if(flag[0])            printf("Yes\n");         else printf("No\n");     }    }}



0 0