LCA即最小公共祖先,tarjan为LCA的离线算法, 可通过dfs和并查集实现。
算法核心思想是用dfs遍历整个树,在遍历到底层返回过程中将当前节点的祖先设为其父亲节点,并遍历需要求解的两点中以当前节点为起点的另外一点是否已访问过,若已访问过,则该答案就是另外一节点当前的祖先。具体看代码注释。
核心代码:
void tarjan(int u)
{
vis[u] = true;//标记
for(int i = head[u]; i != -1; i = edge[i].nex)//遍历当前节点的儿子
{
int v = edge[i].v;
if(vis[v]) continue;//若访问过, 跳过,主要是为了防止查找其父亲节点,若是单向边可以省去
tarjan(v);
Union(v, u);//将v并到u的祖先里
}
vector<Node>::iterator it = q[u].begin();
for(; it != q[u].end(); it++)//需要查找的边里有没有以u为起点
{
if(vis[(*it).v])
{
ans[(*it).id] = find((*it).v);<