先来一波理论
祖先
若u的祖先集合是
那么
su={{u,sfu}uu≠rootu=root
通俗点讲:su就是u和
LCA
设一颗有根树上的两点u,v,它们的LCA为lu,v
那么lu,v∈su⋃sv并且slu,v∈su⋃sv
也就是它们的公共祖先中深度最小的点
来一波tarjan
前叙
tarjan是一个神奇的算法,它的复杂度是O(n+q),加上,好吧,别学我。vector
的大常数,妥妥的TLE
神奇的tarjan的神奇的算法
先奶一波代码
void LCA(int s)
{
ved[s]=1;//如果把连向父亲节点的边删掉,就不用这一步
fr(i,0,t[s].size()-1)
if(!ved[t[s][i]])
{
LCA(t[s][i]);
f[t[s][i]]=s;
}
fr(i,0,as[s].size()-1)
if(vis[as[s][i]])
ans[nu[s][i]]=getf(as[s][i]);
vis[s]=1;
}
tarjan就是后序遍历发现没
举个栗子
我们要求:
1 3
3 4
2 5
4 5
我们先沿着1→2→3欢快得走下去,
然后无路可走了QAQ,接着就留下个标记,XXX到3一游
,并给3了一个flag
:从
然后又回到了2,接着走到了
等等。。。3之前也走过,所以,找到flag
2,于是
然后继续走,给2立了flag
然后到了5,发现了一件大事:flag
flag
往上浪,于是就4→2→1,l4,5=1
然后回了1,没地方放flag
了,那就跳过吧。
然后发现:flag
走,得l1,3=1
所以答案为:
1
2
1
1