好像LCA的題目並不多,現在就做了10道左右,但是找不到別的了,在此做個小總結,將來有更好的題目會不斷更新
解決LCA問題,一般用3種方法
1.樸素方法:兩個點都一直沿路徑往上走,直到有某一個節點被經過兩次並且是第一次出現這樣的點,那麼這個就是LCA
此方法最好理解,但是用得不多,但不代表沒作用,有些題目還是需要用到的
2.LCA轉RMQ(線上演算法):一般是將LCA轉為RMQ問題,用ST演算法求解,當然求解RMQ問題有很多方法,不過ST比較常用而已,這樣做能及時回答每一個詢問
3.Tarjan演算法(離線演算法):利用Tarjan演算法,不過要先讀入所有詢問再一併回答,建議認真學習Tarjan演算法本質
******具體問題具體分析,但是可以使用Tarjan演算法的時候推薦使用Tarjan演算法,代碼量少速度快,另外Tarjan演算法容易產生變形,值得深究*************
hdu 2586 How far away ?
模板題,直接求LCA,可以線上,離線演算法均可解,可以測試一下模板
poj 1986 Distance Queries
模板題,直接求LCA
hdu 2874 Connections between cities
模板題,不過不是樹是森林,所以某些點不存在LCA,要做判斷
zoj 3195 Design the city
任然算是模板題,上面的題要求兩點間的最短距離,這裡要求3點間的最短距離,其實就是兩兩之間求一次LCA並計算出距離,然後相加除以2即可
hdu 3078 Network
LCA + 修改點權值 + 排序:每個點有初始的權值,一邊查詢一邊伴隨著修改某些點的權值,查詢是從a到b路徑中第k大的權值是多少。不需要太多的技巧,修改操作就直接修改,查詢操作先求LCA,然後從a走到b儲存下所有的權值,排序,然後直接輸出即可
poj 2763 Housewife Wind
LCA + 修改邊權:一邊查詢兩點間的距離,一邊修改某些邊權。對於修改了某些邊的邊權,就要從此開始遍曆下面的子孫後代更改他們的dir值(點到根的距離)。也不需要太多技巧,直接按題意實現即可,不過時間比較糟糕,用線段樹或樹狀數組可以對修改操作進行最佳化,時間提升很多
poj 3694 Network
連通分量 + LCA : 先縮點,再求LCA,並且不斷更新,這題用了樸素方法來找LCA,並且在路徑上做了一些操作
poj 3417 Network
LCA + Tree DP : 在運行Tarjan處理完所有的LCA詢問後,進行一次樹DP,樹DP不難,但是要想到用樹DP並和這題結合還是有點難度
poj 3728 The merchant
LCA + 並查集的變形,最佳化:好題,難題,思維和代碼實現都很有難度,需要很好地理解Tarjan演算法中並查集的本質然後靈活變形,需要記錄很多資訊(有點dp的感覺)
hdu 3830 Checkers
LCA + 二分:好題,有一定思維難度。先建立出二叉樹模型,然後將要查詢的兩個點調整到深度一致,然後二分LCA所在的深度,然後檢驗