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 }

 

posted on 2017-07-26 11:37  hhhhx  阅读(98)  评论(0编辑  收藏  举报

导航