第一次接觸lca,是在 scu 3365 , 模板題,當時我是用 disjkstra 加記憶做的,還不會 lca。後來學習 tarjan 演算法,其實還是深搜,當時處理並記錄,tarjan 用來寫 hdu 2586 還是過得去,但是在 scu 3365 卻一直超時,可能 tarjan 演算法在某些資料上效率很低吧。
今天學習 lca 的倍增做法: scu 3365
先 dfs 或者 bfs 找到每個節點當前的父親,然後 dp 處理,用乙個陣列記錄往上跳 2^j 個記錄的節點,所以可以跳的很快,一般的資料 18 次或者 20 次就夠了。求兩點的最近公共祖先,倍增做法是先把深度更大的,也就是樹從起點往下看更低的點,提到(也可以倍增跳)和另乙個點同一高度,然後再 2^j 個步數地同時往上跳,保持一致,最後找出 lca。
求向上跳 2^j 個節點:
void get_dp() e[1005<<1] ;
void add( int u , int v , int cost )
void dfs( int u )
}void get_dp()
int main()
dep[1] = 1 , dis[1] = 0 ; // 初始化起點資訊
dfs( 1 ) ; // 獲取每個點的 fa[i][0], 前驅, 更新距離 dis
get_dp() ; // 獲取每個節點向上跳 2^i 的點
while( q-- )
} return 0 ;
}
SCU 3365 學習 LCA 的線段樹做法
傳送門 scu 3365 前面我也寫過 scu 3365 倍增的解法 scu 3365 st 表的解法 scu 3365 disjkstra 的解法 其實,lca 既然可以用 st 表求 rmq 區間最值 來找,也當然可以用線段樹求區間最值來找啦,也不乏樹狀陣列求區間最值,還有直接遍歷 雖然很慢,但...
學習筆記 lca 倍增
求一棵樹上兩個節點的最近公共祖先有兩種演算法 tarjan 離線 這篇博文只介紹倍增的寫法.f i j 表示節點 i 的祖先中,與節點 i 距離為 2 j 的節點編號.那麼 f i j beginroot i root father i j 0,i not root f i j f f i j 1 ...
《學習筆記》 倍增 lca
例題 codevs 2370 小機房的樹 簡單來說就是給你乙個n個點的樹,每一條邊都有邊權。詢問有m次,每次給出兩個點,求他們之間的最小邊權和。很容易想到用求樹上字首和和lca,先把兩個點跳到高度相同的地方,再一直往上跳,直到兩個點重合。因為乙個點乙個點的跳太慢了,所以我們倍增的跳來求lca。令f ...