空降题目处(外网)
点我点我点我
空降题目处(内网)
点我点我点我
Description
已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。
Input
输入第一行包括一个整数n表示节点个数。
接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
第n+2行是一个整数m表示询问个数。
接下来m行,每行两个正整数x和y。
Output
对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。
Solution
倍增…LCA…
你问我是什么?
自行脑补.(邓晗笑)
Code
C++
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,m,a,b,t,x[80001],y[80001],s[40001],e[40001],d[40001][18],l[40001];
void sort(int l,int r);
void bfs(int t,int x,int la);
int ff(int x,int y);
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%d%d",&x[i*2],&y[i*2]);
x[i*2-1]=y[i*2];
y[i*2-1]=x[i*2];
if (y[i*2]==-1)
t=x[i*2];
}
sort(1,n*2);
for (int i=0;i<=n*2;i++)
if (x[i]!=x[i+1])
{
e[x[i]]=i;
s[x[i+1]]=i+1;
}
d[t][0]=-1;
bfs(1,t,-1);
t=1;
for (int i=1;i<=17;i++)
{
t=t*2;
for (int j=1;j<=40000;j++)
if (l[j]>t)
d[j][i]=d[d[j][i-1]][i-1];
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
printf("%d\n",ff(a,b));
}
}
void sort(int l,int r)
{
int i=l,j=r,m=x[(l+r)/2];
do
{
while (x[i]<m)
i++;
while (m<x[j])
j--;
if (i<=j)
{
swap(x[i],x[j]);
swap(y[i],y[j]);
i++;
j--;
}
}
while (i<=j);
if (i<r)
sort(i,r);
if (l<j)
sort(l,j);
}
void bfs(int t,int x,int la)
{
l[x]=t;
d[x][0]=la;
for (int i=s[x];i<=e[x];i++)
if (y[i]!=la)
bfs(t+1,y[i],x);
}
int ff(int x,int y)
{
int ans=2;
if (l[x]<l[y])
{
swap(x,y);
ans=1;
}
for (int i=17;i>=0;i--)
{
if (l[d[x][i]]>=l[y])
x=d[x][i];
}
if (x==y)
return ans;
else
return 0;
}
Pascal
var
n,m,a,b,t,i,j:longint;
x,y:array [0..100000] of longint;
s,e,l:array [-1..50000] of longint;
d:array [0..50000,0..17] of longint;
procedure swap(var x,y:longint);
var
t:longint;
begin
t:=x;
x:=y;
y:=t;
end;
procedure sort(l,r:longint);
var
i,j,m:longint;
begin
i:=l;
j:=r;
m:=x[(i+j) shr 1];
repeat
while x[i]<m do
inc(i);
while m<x[j] do
dec(j);
if i<=j then
begin
swap(x[i],x[j]);
swap(y[i],y[j]);
inc(i);
dec(j);
end;
until i>j;
if i<r then
sort(i,r);
if l<j then
sort(l,j);
end;
procedure bfs(t,x,la:longint);
var
i:longint;
begin
l[x]:=t;
d[x][0]:=la;
for i:=s[x] to e[x] do
if y[i]<>la then
bfs(t+1,y[i],x);
end;
function ff(x,y:longint):longint;
var
ans,i:longint;
begin
ans:=2;
if l[x]<l[y] then
begin
swap(x,y);
ans:=1;
end;
for i:=17 downto 0 do
begin
if (l[d[x][i]]>=l[y]) then
x:=d[x][i];
end;
if x=y then
exit(ans)
else
exit(0);
end;
begin
read(n);
for i:=1 to n do
begin
read(x[i*2],y[i*2]);
x[i*2-1]:=y[i*2];
y[i*2-1]:=x[i*2];
if y[i*2]=-1 then
t:=x[i*2];
end;
sort(1,n*2);
for i:=0 to n*2 do
if (x[i]<>x[i+1]) then
begin
e[x[i]]:=i;
s[x[i+1]]:=i+1;
end;
d[t][0]:=-1;
bfs(1,t,-1);
t:=1;
for i:=1 to 17 do
begin
t:=t*2;
for j:=1 to 40000 do
if l[j]>t then
d[j][i]:=d[d[j][i-1]][i-1];
end;
read(m);
for i:=1 to m do
begin
read(a,b);
writeln(ff(a,b));
end;
end.