樹是一種很常見的資料結構。現在蒜頭君面臨乙個問題,在乙個有 n 個節點的樹上,節點編號分別是1…n。蒜頭想知道一些節點之間的最近公共祖先是那些節點。
輸入格式
第一行輸入乙個整數 n(2≤n≤10,000),表示樹上有 n 個節點。
接下來的 n−1 行,每行輸入倆個整數 a,b(1≤a,b≤n)代表節點 a,b 之間有一條 a 到 b 邊,a 是 b 的父親。
接下來輸入乙個整數 q,代表蒜頭君的 q 次提問。(1≤q≤1,000)
接下來的 q 行,每行輸入倆個整數 c,d(1≤c,d≤n)代表詢問 c,d 倆個節點的最近公共祖先。
輸出格式
對於每次詢問,輸出公共祖先的節點編號,佔一行。
樣例輸入
51 2
2 31 4
2 52
3 43 5
樣例輸出12
#include
#include
#include
#include
using namespace std;
const
int maxn=
1e4+1;
//最大的點數
struct edge
edge
(int _v,
int _next):v
(_v)
,next
(_next)
//建構函式
}e[maxn]
;int p[maxn]
,vst[maxn]
,d[maxn]
,fa[maxn][20
];//儲存邊的序號的頭指標,標記陣列,儲存深度,fa[i][j]為i往上走(2^j)層的序號
void
dfs(
int u)}}
intlca
(int x,
int y)
int i,j;
for(i=0;
(1<<=d[x]
;++i)
;//找出(2^i<=n),找出i的最大值,保證不會超出樹
--i;
//深的節點先往上走,走到和y節點同一層
for(j=i;j>=0;
--j)}if
(x==y)
return x;
//若走到同一層時,兩者相等,則y就是原先節點的父節點
for(j=i;j>=0;
--j)
if(fa[x]
[j]!=fa[y]
[j])
}return fa[x][0
];//此時x和y的父節點就是最近公共祖先
}int
main()
int root;
for(
int i=
1;i<=n;
++i)
}memset
(d,-1,
sizeof
(d))
;dfs
(root)
;for
(int level=1;
(1<<=n;
++level)
}int q;
scanf
("%d"
,&q)
;while
(q--
)}
模板 LCA 最近公共祖先 倍增法
2019 11 07 09 25 45 c.樹之呼吸 叄之型 樹上兩點路徑長度 time limit 1000 ms memory limit 32768 k total submit 7 4 users total accepted 2 2 users special judge no descr...
LCA最近公共祖先 倍增法筆記
先暫時把模板寫出來,a幾道題再來補充 此模板也是洛谷上的一道模板題 pragma gcc optimize 2 o2優化 include using namespace std typedef long long ll const int l 30 2的指數的大小 const int nn 1e6 ...
倍增法求lca(最近公共祖先)
基本上每篇部落格都會有參考文章,一是彌補不足,二是這本身也是我學習過程中找到的覺得好的資料 大致上演算法的思路是這樣發展來的。想到求兩個結點的最小公共祖先,我們可以先把兩個的深度提到同一水平,在一步一步往上跳,直到兩個結點有了乙個公共祖先,依照演算法流程,這就是least common ancest...