JZOJ 5257. 小X的佛光

来源:互联网 发布:淘宝代销不是长久之计 编辑:程序博客网 时间:2024/04/28 16:40

Description

Description

Input

Input

Output

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

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;}
原创粉丝点击