Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground
题意:给出 一颗树,然后q个询问,每个询问给出3个点,让我们自己选择一个起点一个终点,这条路线上的点标记,问第三个点到终点的最多标记点是多少
思路:第三个点到终点的标记点,肯定是第三个点与起点的最近公共祖先到终点的标记点。我们可以求出三个点的的三种最近公共祖先,取深度最大的点K,然后求K到三个点的距离+1
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 5 const int DEG=17; 6 vector<int> e[N]; 7 int dep[N]; 8 int fa[N][DEG]; 9 10 void dfs(int u){ 11 for(int i=1;i<DEG;i++){ 12 fa[u][i]=fa[fa[u][i-1]][i-1]; 13 } 14 for(int i=0;i<e[u].size();i++){ 15 int v=e[u][i]; 16 dep[v]=dep[u]+1; 17 fa[v][0]=u; 18 dfs(v); 19 } 20 } 21 int lca(int u,int v){ 22 if(dep[u]<dep[v]) swap(u,v); 23 for(int i=0,d=dep[u]-dep[v];d;i++,d>>=1){ 24 if(d&1) u=fa[u][i]; 25 } 26 if(u==v) return v; 27 for(int i=DEG-1;i>=0;i--){ 28 if(fa[u][i]!=fa[v][i]){ 29 u=fa[u][i];v=fa[v][i]; 30 } 31 } 32 return fa[u][0]; 33 } 34 int hh(int u,int v){ 35 return dep[u]+dep[v]-2*dep[lca(u,v)]; 36 } 37 int main(){ 38 int n,q; 39 int x; 40 scanf("%d%d",&n,&q); 41 for(int i=2;i<=n;i++){ 42 scanf("%d",&x); 43 e[x].push_back(i); 44 } 45 dep[1]=1; 46 dfs(1); 47 int k[4]; 48 while(q--){ 49 for(int i=1;i<=3;i++) scanf("%d",&k[i]); 50 int x1=lca(k[1],k[2]),x2=lca(k[1],k[3]),x3=lca(k[2],k[3]); 51 int x; 52 if(dep[x1]>dep[x2]) x=x1;else x=x2; 53 if(dep[x]<dep[x3]) x=x3; 54 int y1=hh(x,k[1]),y2=hh(x,k[2]),y3=hh(x,k[3]); 55 56 cout<<max(max(y1,y2),y3)+1<<endl; 57 } 58 return 0; 59 }