hdu4822 求树上到某点比其他两点距离小的点个数

首先如果是两个点那应该从中间切成两半,再判断所属

所以必然需要使用树上倍增==

继而如果是三个点,则需要仔细分情况讨论==

参考别人的分类讨论写的,感觉那个type判断在哪条链很巧妙啊~

  1 #pragma comment(linker,"/STACK:16777216")
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<algorithm>
  5 using namespace std;
  6 struct dian{
  7   int type,u;
  8 };
  9 int now,next[200005],head[200005],point[200005];
 10 int parent[200005][21],size[200005],depth[200005];
 11 void add(int x,int y)
 12 {
 13   next[++now]=head[x];
 14   head[x]=now;
 15   point[now]=y;
 16 }
 17 void dfs(int u,int pre,int deep)
 18 {
 19   int i,v;
 20   parent[u][0]=pre;
 21   size[u]=1;
 22   depth[u]=deep;
 23   for (i=head[u];i!=-1;i=next[i])
 24   {
 25     v=point[i];
 26     if (v==pre) continue;
 27     dfs(v,u,deep+1);
 28     size[u]+=size[v];
 29   }
 30 }
 31 void rmq_build(int n)
 32 {
 33   for (int k=0;k<20;k++)
 34     for (int u=1;u<=n;u++)
 35       if (parent[u][k]==-1) parent[u][k+1]=-1;
 36       else parent[u][k+1]=parent[parent[u][k]][k];
 37 }
 38 int go_up(int u,int deep)
 39 {
 40   for (int k=0;k<=20;k++)
 41     if ((deep>>k)&1) u=parent[u][k];
 42   return u;
 43 }
 44 int rmq_query(int u,int v)
 45 {
 46   if (depth[u]<depth[v]) swap(u,v);
 47   u=go_up(u,depth[u]-depth[v]);
 48   if (u==v) return u;
 49   for (int k=20;k>=0;k--)
 50     if (parent[u][k]!=parent[v][k])
 51       u=parent[u][k],v=parent[v][k];
 52   return parent[u][0];
 53 }
 54 dian get_middle(int a,int b,int ab)
 55 {
 56   int len=depth[a]+depth[b]-2*depth[ab];
 57   dian n1;
 58   if (depth[a]>=depth[b])
 59     n1.type=1,n1.u=go_up(a,(len-1)/2);
 60   else n1.type=2,n1.u=go_up(b,len/2);
 61   return n1;
 62 }
 63 int n;
 64 int cal(int a,int b,int c,int ab,int ac)
 65 {
 66   dian ab_m=get_middle(a,b,ab),ac_m=get_middle(a,c,ac);
 67   if (ab_m.type==1&&ac_m.type==1)
 68     return depth[ab_m.u]>depth[ac_m.u]?size[ab_m.u]:size[ac_m.u];
 69   else if (ab_m.type==2&&ac_m.type==2){
 70       if (depth[ab_m.u]<depth[ac_m.u]) swap(ab_m,ac_m);
 71       if (rmq_query(ab_m.u,ac_m.u)==ac_m.u) return n-size[ac_m.u];
 72       return n-size[ab_m.u]-size[ac_m.u];
 73   }
 74   else{
 75     if (ab_m.type==2) swap(ab_m,ac_m);
 76     int tmp=rmq_query(ab_m.u,ac_m.u);
 77     if (tmp==ab_m.u) return size[ab_m.u]-size[ac_m.u];
 78     return size[ab_m.u];
 79   }
 80 }
 81 int main()
 82 {
 83   int a,b,c,ab,bc,ac,T,m,i;
 84   scanf("%d",&T);
 85   while (T--)
 86   {
 87     scanf("%d",&n);
 88     now=0;
 89     memset(head,-1,sizeof(head));
 90     for (i=1;i<n;i++)
 91     {
 92       scanf("%d%d",&a,&b);
 93       add(a,b); add(b,a);
 94     }
 95     dfs(1,-1,0);
 96     rmq_build(n);
 97     scanf("%d",&m);
 98     while (m--)
 99     {
100       scanf("%d%d%d",&a,&b,&c);
101       ab=rmq_query(a,b),ac=rmq_query(a,c),bc=rmq_query(b,c);
102       printf("%d %d %d\n",
103           cal(a,b,c,ab,ac),cal(b,a,c,ab,bc),cal(c,a,b,ac,bc));
104     }
105   }
106   return 0;
107 }
View Code

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4822

posted on 2015-02-07 04:50  xiao_xin  阅读(285)  评论(0编辑  收藏  举报

导航