hzwer 模擬題 祖孫詢問

          祖孫詢問spa

題目描述

已知一棵n個節點的有根樹。有m個詢問。每一個詢問給出了一對節點的編號x和y,詢問x與y的祖孫關係。code

輸入輸出格式

輸入格式:blog

輸入第一行包括一個整數n表示節點個數。 接下來n行每行一對整數對a和b表示a和b之間有連邊。若是b是-1,那麼a就是樹的根。 第n+2行是一個整數m表示詢問個數。 接下來m行,每行兩個正整數x和y。get

輸出格式:it

對於每個詢問,若是x是y的祖先,輸出1;若是y是x的祖先,輸出2;不然輸出0。io

輸入輸出樣例

輸入樣例#1: 複製
10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19
輸出樣例#1: 複製
1
0
0
0
2

說明

對於30%的數據,n, m ≤ 1000。 class

對於100%的數據,n, m ≤ 40000,每一個節點的編號都不超過40000。數據

思路:求出兩點的LCA後,若其中有一個點爲LCA,則這個點爲另外一個點的祖先,輸出 1 或 2,反之,輸出 0di

#include<cstdio>
#include<algorithm>

const int N=40001;
int n,m,tot,root,fa[N],ans[N],head[N],_head[N];
struct Edge{
    int v,nxt;
}edge[N<<1];
struct EDge{
    int x,v,nxt,id;
}_edge[N<<1];

inline int read()
{
    int n=0,w=1;register char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    while(c>='0'&&c<='9')n=n*10+c-'0',c=getchar();
    return n*w;
}

int find(int x)
{return fa[x]==x?fa[x]:fa[x]=find(fa[x]);}

inline void add(int u,int v)
{edge[++tot]=(Edge){v,head[u]};head[u]=tot;}
inline void _add(int x,int u,int v,int i)
{_edge[++tot]=(EDge){x,v,_head[u],i};_head[u]=tot;}

bool vis[N];
void dfs(int now)
{
    vis[now]=true;
    for(int v,i=head[now];i;i=edge[i].nxt)
        if(!vis[v=edge[i].v])
            dfs(v),fa[v]=now;
    for(int x,i=_head[now];i;i=_edge[i].nxt)
        if(vis[_edge[i].v])
        {
            x=find(_edge[i].v);
            if(x==now)
                ans[_edge[i].id]=(now==_edge[i].x?1:2);
        }
}

int main()
{
    n=read();
    for(int i=1;i<=N;++i)
        fa[i]=i;
    for(int u,v,i=1;i<=n;++i)
    {
        u=read(),v=read();
        if(v==-1)
            root=u;
        else    add(u,v),add(v,u);
    }
    tot=0;m=read();
    for(int x,y,i=1;i<=m;++i)
    {
        x=read(),y=read();
        _add(x,x,y,i),_add(x,y,x,i);
    }
    dfs(root);
    for(int i=1;i<=m;++i)
        printf("%d\n",ans[i]);
    return 0;
}
相關文章
相關標籤/搜索