倍增算法2(树上倍增)

Posted lnu161403214

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了倍增算法2(树上倍增)相关的知识,希望对你有一定的参考价值。

还是基本的问题,求LCA。

详情见:

https://blog.csdn.net/saramanda/article/details/54963914

 

讲得非常好了。

fa[i][j]=fa[ fa[i][j-1] ][j-1]

用文字叙述为:i的第2^j个父亲 是i的第2^(j-1)个父亲的第2^(j-1)个父亲。

很有回溯的味道,实现也是用的回溯法(dfs),注意这里的第二维表示是i+2^j,而上一篇文章的是i+2^j-1。

任何一个数换成二进制后,都能想到可由∑2x 表示,一个长区间便能用logn个小区间凑起来,知道了这个性质便能很好的理解代码。

 1 #include<algorithm>
 2 #include<iostream>
 3 #include<cstring>
 4 #include<cstdio>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 const int maxn = 100005;
 9 const int max0 = 25;
10 int fa[maxn][max0+5]={0},dep[maxn];
11 vector<int>vt[maxn];
12 void dfs(int x)
13 {    //更新x的st表 
14     for(int i=1;i<=max0;i++) 
15         if(fa[x][i-1])   
16             {
17             fa[x][i]=fa[fa[x][i-1]][i-1];
18            
19               }
20         else break; 
21         
22     int l=vt[x].size();   
23     for(int i=0;i<l;i++)
24         {    int t=vt[x][i];
25         
26             if(t!=fa[x][0])     //无向图也行 
27             {    
28                 fa[t][0]=x;       
29                 dep[t]=dep[x]+1;     
30                 dfs(t);
31             }
32         }
33 }
34 
35 int LCA(int u,int v)
36 {    //对齐 
37     if(dep[u]<dep[v])swap(u,v);  
38     int delta=dep[u]-dep[v];  
39   
40     for(int x=0;x<=max0;x++) //倍增凑步数  
41         if((1<<x)&delta)
42             u=fa[u][x];
43     if(u==v)return u;
44     
45    //同时向LCA跳跃 
46     for(int x=max0;x>=0;x--)    //由大到小凑数 
47         if(fa[u][x]!=fa[v][x])   //判断是否超过LCA 
48         {
49             u=fa[u][x];
50             v=fa[v][x];
51         }
52         
53     return fa[u][0];    
54 }
55 int ind[maxn];
56 int main()
57 {
58     int n;
59     cin>>n;
60     
61     for(int i=1;i<n;i++)
62     {
63         int x,y;
64         cin>>x>>y;
65         vt[x].push_back(y); //有向图 
66         ind[y]++; //入度++ 
67     }
68     int i=1;
69     
70     for(;i<=n;i++)
71     {
72         if(ind[i]==0) break;
73     }
74     dfs(i);
75     int m;
76     cin>>m;
77     while(m--)
78     {
79         int x,y;
80         cin>>x>>y;
81         cout<<LCA(x,y)<<endl;
82     
83     }
84 }
85  

 

以上是关于倍增算法2(树上倍增)的主要内容,如果未能解决你的问题,请参考以下文章

B20J :5165: 树上倍增

BZOJ5165: 树上倍增

树上倍增——(货车运输 解题报告)

树上倍增求LCA

图论-最近公共祖先-在线树上倍增

倍增法求LCA