12 16 樹上倍增法求LCA

2021-09-03 07:07:23 字數 1235 閱讀 6681

1.預處理:節點的深度d、到根節點的距離dist、該點向上走2^k步能夠到達的點:f陣列。

2.lca:

①.將兩個節點調整到同乙個深度,只調整深的那個即可。

②.如果①結束後,這兩個點重合,說明該點就是所求的點。

③.否則,從大往小開始試跳躍的步數,直至將這兩個點調整為目標點的兩個子節點。

最後兩點的父節點就是所求的lca。

題意:給一顆n個點的樹以及n-1條邊的權值,m次查詢,查詢指定兩個點之間的距離。

分析:樹之間的路徑肯定就是兩點之間的最短路了,但是如果弗洛伊德演算法40000*40000*10會超時,

dijkstra演算法的話15*200*40000*10也會超時。所以那幾個求最短路的演算法都不能用了。

然後根據題解,用 lca的方法時間複雜度 o((n+m)logn)。

因為x到y的距離,可以看做x到根節點的距離+y到根節點的距離-2*lca到根節點的距離

所以可以先求lca,又因為樹作為特殊的圖,兩節點之間有且僅有一條通路且一定為最短路,

所以求深度、求最短路的操作是可以同時進行的(spfa,dijkstra均可以),最後,套用上面

的公式即出結果。

ac**:

#define ll long long

using namespace std;

const int size=50010;

int f[size][20],d[size],dist[size];

int ver[2*size],next[2*size],edge[2*size],head[size];

int t,n,m,tot,t;

queue q;

void add(int x,int y,int z)

void bfs()//預處理,求深度、最短路,f陣列;就是spfa,時間複雜度o(nlogn)

int main()

{ cin>>t;

while(t--)

{cin>>n>>m;

t=(int)(log(n))/log(2)+2;

//這裡限制向上的最大步數,為什麼是這個?不知道.

cout<>x>>y;

cout

樹上倍增法求LCA

我們找的是任意兩個結點的最近公共祖先,那麼我們可以考慮這麼兩種種情況 1.兩結點的深度相同.2.兩結點深度不同.第一步都要轉化為情況1,這種可處理的情況。先不考慮其他,我們思考這麼乙個問題 對於兩個深度不同的結點,把深度更深的那個向其父節點迭代,直到這個迭代結點和另乙個結點深度相同,那麼這兩個深度相...

演算法 樹上倍增求LCA

lca指的是最近公共祖先 least common ancestors 如下圖所示 4和5的lca就是2 那怎麼求呢?最粗暴的方法就是先dfs一次,處理出每個點的深度 然後把深度更深的那乙個點 4 乙個點地乙個點地往上跳,直到到某個點 3 和另外那個點 5 的深度一樣 然後兩個點一起乙個點地乙個點地...

倍增法求 LCA

預處理 通過dfs遍歷,記錄每個節點到根節點的距離dist u 深度d u 並求出樹上每個節點i的2 j祖先f i j 求最近公共祖先,根據兩個節點的的深度,如不同,向上調整深度大的節點,使得兩個節點在同一層上,如果正好是祖先結束,否則,將連個節點同時上移,查詢最近公共祖先。include incl...