Codeforces Round #294 (Div. 2) E

来源:互联网 发布:win7 for mac 安装iso 编辑:程序博客网 时间:2024/05/18 23:12

题目大意:给你一棵有n个节点的树。再给你m个询问,每次询问A,B。问你树上到A,B距离相等的点有几个。


这场DIV2为何这么水 = =而且我竟然没报名参赛。。。

这题直接用倍增LCA即可

用son[]表示子节点个数

求出A B的链长度

然后求出链的中点X

这里分类讨论一下

dep[A]==dep[B]

ans=n-A跳到X的子树-B跳到X的子树

dep[A]!=dep[B]

ans=son[x]-B跳到X的子树

然后就弄完了



#include<queue>#include<cstdio>#include<string>#include<cstring>#include<algorithm>using namespace std;struct line{     int s,t;     int next;}a[1000001];int head[500001];int edge;inline void add(int s,int t){     a[edge].next=head[s];     head[s]=edge;     a[edge].s=s;     a[edge].t=t;}bool v[500001];int deep[500001];int ans[500001][22];inline void bfs(int r){     int i,j;     deep[r]=1;     for(i=0;i<=21;i++)          ans[r][i]=r;     queue <int>Q;     while(!Q.empty())          Q.pop();     Q.push(r);     v[r]=true;     while(!Q.empty())     {          int d=Q.front();          Q.pop();          for(i=head[d];i!=0;i=a[i].next)          {               int t=a[i].t;               if(!v[t])               {                    v[t]=true;                    Q.push(t);                    deep[t]=deep[d]+1;                    ans[t][0]=d;                    int dt;long long dc;                    for(j=1;j<=21;j++)                    {                     dt=ans[t][j-1];                         ans[t][j]=ans[dt][j-1];                    }               }          }     }}int son[100001];inline void dfs(int d){     int i;     for(i=head[d];i!=0;i=a[i].next)     {       int t=a[i].t;          if(t!=ans[d][0])          {               dfs(t);               son[d]+=son[t];          }     }     son[d]++;}inline int swim(int x,int y){     while(deep[x]!=deep[y])     {          int i=0;          while(deep[ans[y][i]]>deep[x])               i++;          if(i!=0)               i--;          y=ans[y][i];     }     return y;}inline int swimx(int x,int y){ int i=1; for(int pt=1;pt<=22;pt++)      i=i*2; int pt=22;     while(x!=0)     {          while(i>x)          {               i/=2;               pt--;          }          y=ans[y][pt];          x-=i;     }     return y;}inline int lca(int x,int y){     if(deep[x]>deep[y])     {          int t=x;          x=y;          y=t;     }     y=swim(x,y);     int i=21;     while(x!=y)     {          while(ans[x][i]==ans[y][i]&&i>0)               i--;          x=ans[x][i];          y=ans[y][i];     }     return x;}int fa[100001];inline int find(int x){     if(fa[x]!=x)          fa[x]=find(fa[x]);     return fa[x];}int main(){     int n,m;     scanf("%d",&n);     int i,s,t;     for(i=1;i<=n-1;i++)     {          scanf("%d%d",&s,&t);          edge++;          add(s,t);          edge++;          add(t,s);     }     bfs(1);     dfs(1);     scanf("%d",&m);     for(i=1;i<=m;i++)     {          scanf("%d%d",&s,&t);          if(s==t)               printf("%d\n",n);          else          {             if(deep[s]>deep[t])             {                  int xt=s;                  s=t;                  t=xt;             }               int tx=lca(s,t);               int len=0;               if(tx==s)                    len=deep[t]-deep[s];               else                    len=deep[s]-deep[tx]+deep[t]-deep[tx];               if(len%2==1)                    printf("0\n");               else if(deep[s]!=deep[t])               {                    int yy=swimx(len/2-1,t);                    int anst=son[ans[yy][0]]-son[yy];                    printf("%d\n",anst);               }               else if(deep[s]==deep[t])               {                    int yy=swimx(len/2-1,t);                    int xx=swimx(len/2-1,s);                    int anst=n-son[yy]-son[xx];                    printf("%d\n",anst);               }          }     }     return 0;}


0 0
原创粉丝点击