Description
Input
Output
Sample Input
3 3 1
1 2
2 3
1 2 3
1 1 3
3 1 3
Sample Output
1
1
3
Data Constraint
Hint
样例2、3、4见所附文件
Solution
题目给出一个无根树,于是我们先以 1 位根,将树转成有根树,可以发现这不影响答案。
同时记录点的深度和父亲等信息,用倍增预处理出点的 Lca 信息。
接着,对于一个询问,求出两两之间的 Lca ,分类讨论其摆布情况,通过深度算出答案即可。
特别注意的是分类讨论情况繁琐,切勿漏判,时间复杂度为 O((N+Q) log N) 。
Code
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=2e5+1;
int tot;
int first[N],next[N<<1],en[N<<1];
int dep[N],f[N][18];
inline int read()
{
int X=0,w=1; char ch=0;
while(ch<'0' || ch>'9') {if(ch=='-') w=-1;ch=getchar();}
while(ch>='0' && ch<='9') X=(X<<3)+(X<<1)+ch-'0',ch=getchar();
return X*w;
}
inline int max(int x,int y)
{
return x>y?x:y;
}
inline void insert(int x,int y)
{
next[++tot]=first[x];
first[x]=tot;
en[tot]=y;
}
inline void dfs(int x)
{
dep[x]=dep[f[x][0]]+1;
for(int i=first[x];i;i=next[i])
if(en[i]!=f[x][0])
{
f[en[i]][0]=x;
dfs(en[i]);
}
}
inline int lca(int x,int y)
{
if(dep[y]>dep[x]) swap(x,y);
for(int i=log2(dep[x]);i>=0;i--)
if(dep[f[x][i]]>=dep[y]) x=f[x][i];
if(x==y) return x;
for(int i=log2(dep[x]);i>=0;i--)
if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
return f[x][0];
}
int main()
{
int n=read(),q=read(),num=read();
for(int i=1;i<n;i++)
{
int x=read(),y=read();
insert(x,y);
insert(y,x);
}
dfs(1);
for(int j=1;j<=17;j++)
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
while(q--)
{
int a=read(),b=read(),c=read(),ans=0;
int ab=lca(a,b),ac=lca(a,c),bc=lca(b,c);
if(ab==b)
{
if(dep[ac]<=dep[b]) ans=1; else ans=dep[ac]-dep[b]+1;
}else
if(ab==a)
{
if(dep[bc]<=dep[a]) ans=dep[b]-dep[a]+1; else ans=dep[b]-dep[bc]+1;
}else
{
if(ac==a) ans=dep[a]+dep[b]-2*dep[ab]+1; else
if(bc==b) ans=1; else
if(bc==c) ans=dep[b]-max(dep[c],dep[ab])+1; else
if(ac==c)
{
ans=dep[b]-dep[ab]+1;
if(dep[c]>dep[ab]) ans+=dep[c]-dep[ab];
}else
if(bc==ab && ab==ac) ans=dep[b]-dep[bc]+1; else
if(dep[bc]>dep[ab]) ans=dep[b]-dep[bc]+1; else
if(dep[ac]<dep[ab])
{
if(dep[ab]>dep[bc]) ans=dep[b]-dep[ab]+1; else
ans=dep[ab]+dep[c]-2*dep[ac]+1;
}else
if(dep[ac]>=dep[ab]) ans=dep[ac]+dep[b]-2*dep[ab]+1;
}
printf("%d\n",ans);
}
return 0;
}