求LCA最近公共祖先的在線倍增算法模板_C++


  倍增求 LCA 是在線的,而且比 ST 好寫多了,理解起來比 ST 和 Tarjan 都容易,於是就自行腦補吧,代碼寫得容易看懂

  關鍵理解 f[i][j] 表示 i 號節點的第 2j 個父親,也就是往上走 2個節點

  求 LCA 的時候先倍增讓兩點深度一樣,再倍增求

  另外丟兩個鏈接,這兩個有詳細講解

    ST 算法 http://www.cnblogs.com/hadilo/p/5837517.html

    Tarajan 算法 http://www.cnblogs.com/hadilo/p/5840390.html

  可能代碼縮進不是很好看,因為我的 Emacs 用的默認縮進

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<iostream>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 const int N=100001,L=20;
10 int m,first[N],next[N],d[N],f[N][L];
11 inline void dfs(int x,int dep)
12 {
13   d[x]=dep;
14   m=max(m,dep);
15   for (int i=first[x];i;i=next[i]) dfs(i,dep+1);
16 }
17 int log2(int x)
18 {
19   int k=0;
20   while (x>1)
21     {
22       x>>=1;
23       k++;
24     }
25   return k;
26 }
27 int main()
28 {
29   int i,j,n,s,x,y,root;
30   scanf("%d",&n);
31   for (i=1;i<=n;i++)
32     {
33       scanf("%d",&f[i][0]);
34       if (!f[i][0]) root=i;
35       next[i]=first[f[i][0]];
36       first[f[i][0]]=i;
37     }
38   dfs(root,0);
39   s=log2(m);
40   for (j=1;j<=s;j++)
41     for (i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];
42   scanf("%d",&n);
43   while (n--)
44     {
45       scanf("%d%d",&x,&y);
46       if (d[x]<d[y]) swap(x,y);
47       s=log2(d[x]-d[y]);
48       while (d[x]>d[y])
49     {
50       if (d[x]-(1<<s)>=d[y]) x=f[x][s];
51       s--;
52     }
53       s=log2(d[x]);
54       while (s>-1)
55     {
56       if (f[x][s]!=f[y][s])
57         {
58           x=f[x][s];
59           y=f[y][s];
60         }
61       s--;
62     }
63       printf("%d\n",x==y?x:f[x][0]);
64     }
65   return 0;
66 }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM