祖孫詢問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
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
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; }