完整部分點這裡
有 n 種辦法可以解決lca問題,這裡我們只講一種,用樹上倍增的方法來實現 lca。
在沒有學習倍增寫lca之前,你是怎麼樣求lca的呢?至少,我是老老實實地讓這兩個點一步一步往上移並找出它們的路徑第一次交匯的地方。這種方法固然可行、好想,但它的效率實在不高。但是,我們完全可以通過提高「這兩個點一步一步往上移」來提高效率。
所以,我們採用倍增的思路來預處理,分別記錄這點的祖先,記錄為anc[i][j]。即為第i個點往上2^j個祖先。比如說,當j=0時,2^j=1,anc[i][j]是第i個點的上乙個節點,即它的父親節點。
那麼該如何預處理出anc陣列呢?
int anc[1005][25], fa[1005], deep[1005];
vectortree[1005];
void dfs(int x)
}
接著,只要呼叫dfs(根節點)就可以初始化anc陣列。
下面,我們來考慮如何處理lca查詢。即每次給你兩點x和y,求出它們的lca(x,y)。在有了anc陣列之後,求出最近公共祖先就會變得很簡單。
首先,讓x,y在同一深度上。在大多數情況下,查詢給你的兩個點x和y它們的深度是不同的。但是,如果兩點的深度相同,我們就可以實現兩個點同時倍增比較何時祖先相同。所以,第一步是使x,y中深度較深的點往上移動直到與另乙個點深度相同。當然,點的移動也可以用倍增完成。
然後,當兩點深度相同後,同時向上倍增兩個點,當它們祖先剛好相同時,這個祖先就是它們的lca。
int lca(int x, int y)
return anc[x][0];
}
我們首先讓x成為深度較深的點,第乙個for讓x和y的深度相同。如果y是x的祖先,直接可以退出。然後同時開始倍增直至到達同個節點。輸出。 樹上倍增求LCA(最近公共祖先)
前幾天做faebdc學長出的模擬題,第三題最後要倍增來優化,在學長的講解下,嘗試的學習和編了一下倍增求lca 我能說我其他方法也大會嗎?倍增求lca father i j 表示節點i往上跳2 j次後的節點 可以轉移為 father i j father father i j 1 j 1 此處注意迴圈...
講解 模板 最近公共祖先(LCA)(倍增)
閱讀須知 我認為讀者已經掌握 或了解 了 倍增思想 樹 圖 的基本概念及簡單實現 存圖與建圖 dfs 嗯,我們來看看最近公共祖先 lca 的一種實現方式 倍增。話說什麼是最近公共祖先呢?emmm 大家如果知道樹的話,應該就知道父親節點與兒子節點了吧,那麼祖先就是父親的父親的父親的 總之在同一條樹鏈上...
模板 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...