Tarjan離線演算法 (LCA最近公共祖先)

2022-04-30 04:30:10 字數 1875 閱讀 9401

tarjan離線演算法是利用並查集和dfs來達到離線處理的目的

我們都知道,對於一棵樹,後序遍歷一遍,訪問它的根的時機一定是後與它的孩子的。換一句話,當開始遍歷它的根節點的時候,它遍歷過的孩子的公共祖先一定是這個根而這也就成為了我們解題的思想。

由於是需要對整樹進行dfs,所以tarjan需要在所有資訊都輸入完畢後才能進行操作,這也是為什麼要離線的原因

找到入度為0的點u(根節點)

tarjan(u)

訪問r的每個子結點v,如果該子結點v未被訪問,tarjan(v)

將c加入到父親結點u中

標記v為已訪問

處理關於u的查詢,若查詢(u,v)中的v已遍歷過,則lca(u,v)= v所在的集合的祖先,即find(v);

最後來一道例題吧

poj1470

一道模板題,直接放**了

#include 

#include

#include

#include

#include

#include

#include

#include

#define pb push_back

#define lowbit(a) (a&(-a))

#define fori(a) for(int i=0;i#define forj(a) for(int j=0;j#define ifor(a) for(int i=1;i<=a;i++)

#define jfor(a) for(int j=1;j<=a;j++)

#define _mem(a,b) memset(a,0,(b+3)<<2)

#define mem(a,b) memset(a,b,sizeof(a))

#define in freopen("in.txt","r",stdin)

#define out freopen("out.txt","w",stdout)

#define io dowhile(0)

using

namespace

std;

typedef

long

long ll;

const

int maxn = 1e4+10;

const

int maxn = 1e6+10;

const

int inf = 0x3f3f3f3f;

const

int inf = 0x3f;

const

double eps = 1e-7;

const

double pi = acos(-1);

const

int mod = 1e9+7;

vector

a[maxn]; //鄰接表存圖

vector

q[maxn]; //鄰接表存查詢

int p[maxn]; //並查集中的father陣列

bool v[maxn]; //是否被訪問

bool root[maxn]; //根節點

int res[maxn]; //答案陣列

int n;

int find(int x)

void join(int root1, int root2)

void tarjan(int u)

fori(q[u].size())

}void init()

}int main()

}scanf("%d",&t);

while(t--)

ifor(n)

}ifor(n+1)

LCA離線演算法tarjan

lca演算法 lca least common ancestor 是指在一棵樹中,距離兩個點最近的兩者的公共節點。也就是說,在兩個點通往根的道路上,肯定會有公共的節點,我們就是要求找到公共的節點中,深度盡量深的點。還可以表示成另一種說法,就是如果把樹看成是乙個圖,這找到這兩個點中的最短距離。本文先介...

LCA 離線tarjan演算法

對於最近公共祖先問題,我們先來看這樣乙個性質,當兩個節點 u,v 的最近公共祖先是x時,那麼我們可以確定的說,當進行後序遍歷的時候,必然先訪問完x的所有子樹,然後才會返回到x所在的節點。這個性質就是我們使用tarjan演算法解決最近公共祖先問題的核心思想。同時我們會想這個怎麼能夠保證是最近的公共祖先...

LCA 最近公共祖先 離線演算法之tarjan

初步學習了一下用tarjan演算法求最近公共祖先 lca 下面是敝人的拙見 tarjan是乙個離線演算法,所謂離線演算法就是在所有詢問均儲存完之後再做操作。而tarjan演算法對這些詢問並不一定按儲存時的順序去操作,這就是tarjan演算法的時間複雜度能達到o n q 的關鍵所在 q為詢問的數量 至...