基本上每篇部落格都會有參考文章,一是彌補不足,二是這本身也是我學習過程中找到的覺得好的資料
大致上演算法的思路是這樣發展來的。
想到求兩個結點的最小公共祖先,我們可以先把兩個的深度提到同一水平,在一步一步往上跳,直到兩個結點有了乙個公共祖先,依照演算法流程,這就是least common ancestor。
但是如果這樣一步步地往上未免太讓人著急,為了提高一下效率,便不再每次只跳一步,而跳\(2^i\)步。一般的,先這樣蹦蹦跳跳跳上去直到兩個結點相平,在兩個一起這樣蹦上去。
怎麼確定這個i該是多少合適呢?
這裡我們需要預處理乙個陣列f,f[u] [i]來表示結點u的第i代祖先,f[u] [0]表示結點u的父親,這個陣列用鏈式前向星(最近怎麼老是它)加上dfs來預處理產生,十分便捷。那它有什麼用呢?用在提公升結點的時候,我們可以借助這個陣列直接將結點提到他的合適的祖先上去。怎麼才算合適的祖先?現假設求lca(s,t)
分兩步,第一步是將低結點提到高結點(相對於葉節點)的深度上。這時候乙個for迴圈從s的第20代祖先開始(為什麼是二十代?可能一般的樹達不到這個深度),看能不能把s提上去後滿足\(depth[s]>=depth[t]\),不能滿足就看第十九代祖先這樣一直減少i,若滿足了就把s提上去,還是繼續減少i,直到兩個結點最終相平。這個過程有個部落格裡講的很形象(見參考文章),比喻成烏鴉喝水的過程,就是烏鴉先把體積大的(這裡就是i值)放進水杯裡,再逐漸減小放入物品的體積直到把水杯的水公升上來,而不是先填沙子這種小顆粒的東西。這就是為什麼i值要從大到小。
第二步是整體提公升的過程,我們不知道該幾步提公升,在迴圈中的條件就變成了\(if(f[s][i]!=f[t][i])\)。也就是只要他兩的祖先不一樣就提公升,祖先一樣有兩種可能,一種可能是節點是祖先但不是最小公共祖先,另一種可能是到了公共祖先。前一種出現在迴圈的開始,一開始想要提的深度比較多,所以很可能提到了公共祖先。這種情況不用管,繼續減小i值,之後可能會由於滿足\(if\)條件而經歷一些兩點提公升的過程,最後不滿足\(if\)條件了,說明兩個已經有了最小公共祖先,這時候隨意輸出乙個節點的父結點就行了。
演算法完成,看看**。如覺得不太清楚請看參考文章。
#include #include #define max_n 500005
using namespace std;
int n,m,s;//n為結點數,m為邊數,s為根節點標號
int lg[max_n];//優化用到的預處理的陣列,存log_2[i]-1
int f[max_n][23];//f[u][i]表示結點u的第i代祖先,其中f[u][0]為u的父結點
int depth[max_n];//節點深度
//鏈式前向星
int head[max_n];
struct edge
e[max_n<<1];
int cnt = 0;
void add(int u,int v)
//快速讀入模板
inline void read(int& x)
while('0'<=ch&&ch<='9')
x = f?-x:x;
}//dfs預處理出結點往上跳2^i的結點
void dfs(int u,int from)
if(s==t)//若t為s的祖先
for(int i = lg[depth[s]]-1;i>=0;i--)//待s,t相平後
}/*for(int i = 20;i>=0;i--)
}*/return f[s][0];//直到最後兩者公共祖先相等,記為lca
}int main()
for(int i = 1;idfs(s,0);
int ans = 0;
for(int i = 1;i<=m;i++)
return 0;
}
樹上倍增求LCA(最近公共祖先)
前幾天做faebdc學長出的模擬題,第三題最後要倍增來優化,在學長的講解下,嘗試的學習和編了一下倍增求lca 我能說我其他方法也大會嗎?倍增求lca father i j 表示節點i往上跳2 j次後的節點 可以轉移為 father i j father father i j 1 j 1 此處注意迴圈...
模板 LCA 最近公共祖先 倍增法
2019 11 07 09 25 45 c.樹之呼吸 叄之型 樹上兩點路徑長度 time limit 1000 ms memory limit 32768 k total submit 7 4 users total accepted 2 2 users special judge no descr...
LCA最近公共祖先 倍增法筆記
先暫時把模板寫出來,a幾道題再來補充 此模板也是洛谷上的一道模板題 pragma gcc optimize 2 o2優化 include using namespace std typedef long long ll const int l 30 2的指數的大小 const int nn 1e6 ...