倍增法求LCA代碼加詳細註釋

 1 #include <iostream>
 2 #include <vector>
 3 #include <algorithm>
 4 #define MAXN 100
 5 //2^MAXLOG2>=最大深度 
 6 #define MAXLOG2 7
 7 using namespace std;
 8 
 9 vector<int>G[MAXN];
10 int depth[MAXN];
11 int ancestor[MAXN][MAXLOG2]; 
12 
13 void creat()//輸入並存儲樹 
14 {
15     int n,x,y;
16     cin>>n;//n條邊 
17     for(int i=0;i<n;i++)
18     {
19         cin>>x>>y;
20         G[x].push_back(y);
21         G[y].push_back(x);
22     }
23 }
24 void dfs(int x,int father)
25 {
26     depth[x]=depth[father]+1;//計算x深度 
27     ancestor[x][0]=father;
28     //計算x結點的2^i步祖先 
29     for(int i=1;i<MAXLOG2;i++)
30         //由於是dfs,因此深度小的結點的ancestor總會先算出來 
31         //MAXLOG2太大了會怎樣?由於ancestor[0][i]=0,因此無論怎樣往上走都是0 
32         ancestor[x][i]=ancestor[ancestor[x][i-1]][i-1]; 
33     for(int i=0;i<G[x].size();i++)
34         if(G[x][i]!=father)dfs(G[x][i],x);
35 }
36 int lca(int x,int y)
37 {
38     if(depth[x]<depth[y])swap(x,y);
39     /*假設x與y深度相差z,x每次走2^i(i從最大每次循環減小1)步總能到達y的深度
40     證實:將z轉換成二進制,再轉換成十進制
41         則確定等於2^i1 + 2^i2 + 2^i3 ... 形式  */
42     for(int i=MAXLOG2-1;i>=0;i--)
43         //如何防止走多了?走完後的深度比y還小,說明走多了,這時候咱們就不走 
44         if(depth[ancestor[x][i]]>=depth[y])x=ancestor[x][i];
45     if(x==y)return x;
46     //假設x與LCA相距L步,那麼x,y都走L-1步仍然不相等,下面的循環是讓x,y走L-1步
47     for(int i=MAXLOG2-1;i>=0;i--)
48         /*如何防止走多了?
49          注意循環結束條件,並不是當x,y走完後相等
50          若是以x,y相等爲結束條件,則有可能會走過了 
51          此循環的目的是爲了讓x,y走L-1步  
52          LCA至關於x,y的中點
53          爲何必定恰好走L-1步?
54          首先能肯定的是存在兩個結點再往上一步就是LCA
55          此循環讓x,y只要不相等就往上走,x,y確定會到達這兩個結點 
56          即x,y走L-1步會到達那兩個結點。本身能夠畫圖試試*/
57         if(ancestor[x][i]!=ancestor[y][i])
58         {
59             x=ancestor[x][i];
60             y=ancestor[y][i];
61         }
62     return ancestor[x][0]; //即x再向上走1(2^0)步便是LCA    
63 }
64 int main()
65 {
66     creat();//數據要輸入 
67     dfs(1,0);
68     //cout<<lca(7,6);
69     return 0;
70 }
相關文章
相關標籤/搜索