在一棵樹中,兩個結點之間第乙個共同的祖先。
如圖:
結點10和11的公共祖先有1、7、8、⑨四個節點,但是只有⑨是離其最近的,所以只有⑨是lca
同理,3和11的lca即是根節點1。2和4的lca是2。
其實講個道理,我也不知道究竟是不是tarjan演算法,因為網上說這個dfs序離線做法不是tarjan啥的,姑且這麼叫吧。。反正複雜度也是很低
作為oi利器**師–dfs–深度優先搜尋
據說是只要你dfs學得好,你就能一等,你就能拿金
所謂dfs序,就是按照dfs遍歷的順序記錄下點的順序。
再比如,還是上圖為例:
若是我們遍歷的順序是從左到右,則dfs序是這樣的:
有這個例項在,應該可以理解了吧。既然提到了dfs序的概念,我想很多人已經知道接下來怎麼求lca了
沒錯,就是在兩個結點中找到深度最小的那個結點。
沒有想象中的複雜吧。。這就是演算法的迷人之處呢。
**:
#include
#include
#include
#define maxn 100005
using
namespace
std;
struct nodeedge[maxn];
int c=0,lc,ans,e=0,q,n,m;
int find_p[maxn],dfs_d[maxn],dfs_p[maxn],dfs_w[maxn],head[maxn];
void add(int u,int v,int d)
void dfs_lca(int pre,int now,int deep,int weight)
}c++;//同樣又一次回到了起點
dfs_p[c]=now;
dfs_d[c]=deep;
dfs_w[c]=weight;
find_p[now]=c;//now這個點最後被記錄的位置
return ;
}void lca()
void find_lca(int u,int v)
int main()
lca();
scanf("%d",&q);
for(int i=1;i<=q;i++)
return
0;}
**中使用的資料結構是鍊錶,但是是用陣列模擬的辦法,需要學習這種方法的同學可以去我的另一篇部落格:
祝各位oier武運昌隆!!!
演算法摘記 最近公共祖先LCA Tarjan演算法
在求解最近公共祖先為問題上,用到的是tarjan的思想,從根結點開始形成一棵深搜樹,非常好的處理技巧就是在回溯到結點u的時候,u的子樹已經遍歷,這時候才把u結點放入合併集合中,這樣u結點和所有u的子樹中的結點的最近公共祖先就是u了,u和還未遍歷的所有u的兄弟結點及子樹中的最近公共祖先就是u的父親結點...
最近公共祖先 python 最近公共祖先
lca演算法樸素演算法 也就是我們所說的暴力演算法,大致的思路是從樹根開始,往下迭代,如果當前結點比兩個結點都小,那麼說明要從樹的右子樹中找 相反則從左子樹中查詢 直到找到乙個結點在當前結點的左邊,乙個在右邊,說明當前結點為最近公共祖先,如果乙個結點是另外乙個結點的祖先,那麼返回前面結點的父親結點即...
最近公共祖先 LCA 最近公共祖先
直接暴力搜尋參考 普通搜尋每次查詢都需要 樸素演算法是一層一層往上找,倍增的話直接預處理出乙個 具體做法是 維護乙個 的關係來線性求出這個陣列 int anc n 31 int dep n 記錄節點深度 void dfs int u,int parent for int i 0 i g u size...