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 }