Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

祖孙询问

描述

已知一颗有根树。有m个询问。每个询问给出了一对节点x,y,输出x,y的祖孙关系

輸入

第一行节点数目n接下来n行,每行一对整数a,b,表示a和b之间有边。如果b==-1,那么a就是数根接下来是一个整数m,表示询问的个数接下来m行,每行两个正整数x,y

輸出

对于每一个询问,如果x是y的祖先,输出1;如果y是x的祖先,输出2;否则输出0

輸入範例 1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
2
3
4
5
1
0
0
0
2

提示

对于30%的数据,n,m<=1000对于100%的数据,n,m<=40000,每个节点的编号都不超过40000

思路

将深的那个节点一直往上跳,跳到同一深度后如果是同一个节点那一个就是另一个的祖先。

好吧大概搞懂什么是倍增了。

第一次把树写到结构体里面。

注意输入的两个节点中,后面那个是爸爸。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include<bits/stdc++.h> 
using namespace std;

const int MAXN=4e4+5,H=16;

struct tree{
public:
void clear(void){
memset(e,0,sizeof(ed));
memset(head,0,sizeof(head));
memset(depth,0,sizeof(depth));
memset(f,0,sizeof(f));
newp=0;
bfsed=0;
}

void vAdd(int p1,int p2){
++newp;
e[newp].to=p2;
e[newp].nex=head[p1];
e[newp].frm=p1;
fa[p2]=p1;
head[p1]=newp;
}

void setSize(int s){
size=s;
h=(log(size)/log(2)+0.5);
}

int getSize(void){
return size;
}

void setRoot(int r){
root_node=r;
}

int root(void){
return root_node;
}

int getDepth(int node){
if(!bfsed){
bfs_for_depth();
}
return depth[node];
}

bool checkFa(int son,int fat){
for(int i=h;i>=0;--i){
if(depth[f[son][i]]>=depth[fat]){
son=f[son][i];
}
}
if(son==fat)return 1;
else return 0;
}


private:
struct ed{
int to,nex,frm;
} e[MAXN];
int head[MAXN],newp,size,root_node,depth[MAXN],fa[MAXN],f[MAXN][H];
bool bfsed;
int h;

void bfs_for_depth(void){
queue<int> q;
depth[root_node]=1;
q.push(root_node);
while(!q.empty()){
int x=q.front();
q.pop();
for(int i=head[x];i;i=e[i].nex){
int y=e[i].to;
depth[y]=depth[x]+1;
f[y][0]=x;
for(int j=1;j<=h;++j){
f[y][j]=f[f[y][j-1]][j-1];
}
q.push(y);
}
}
bfsed=1;
}
};

tree a;

int main(void){
a.clear();
int n,m;
scanf("%d",&n);
a.setSize(n);
for(int i=1;i<=n;++i){
int p1,p2;
scanf("%d%d",&p1,&p2);
if(p2==-1){
a.setRoot(p1);
}
else {
a.vAdd(p2,p1);
}
}

scanf("%d",&m);

for(int i=1;i<=m;++i){
int x,y;
scanf("%d%d",&x,&y);
if(x!=y&&a.getDepth(x)==a.getDepth(y)){
printf("0\n");
}
else{
int ans=0;
int dp1=a.getDepth(x);
int dp2=a.getDepth(y);
if(dp1>dp2){
if(a.checkFa(x,y)){
ans=2;
}
}
else{
if(a.checkFa(y,x)){
ans=1;
}
}
printf("%d\n",ans);
}
}
return 0;
}

评论