最近公共祖先 LCA

一、基本算法

       1、 Tarjan算法基于深度优先搜索的框架,对于新搜索到的一个节点,首先创建有这个节点构成的集合,再对当前节点的每一个子树进行搜索,每搜索完一个子树,则确定子树内的LCA询问都已解决。其他的LCA询问的结果必然在这个子树之外,这时把子树所形成的集合与当前节点的集合合并,并将当前节点设为这个集合的祖先。之后继续搜索下一棵子树。

       2、伪代码:

            (1)建立以u为代表的集合。

            (2)遍历与u相连的节点v,如果v没有被访问过,对于v使用LCA算法,结束后,将v的集合并入u的集合。

            (3)对于与u有关的询问(u, v), 如果v被访问过,则结果就是v所在的集合的代表元素。

       3、代码:

int p[MAXX];
int head[MAXX];   //前向星
int qhead[MAXX];  // 表示询问
struct node
{
    int to;
    int lca;
    int next;
};
node edge[MAXX];   // 边的信息
node qedge[MAXX];  // 表示询问
int Find(int x)
{
    if (p[x] != x)
        p[x] = Find(p[x]);
    return p[x];
}

bool vis[MAXX];
void LCA(int u)
{
    p[u] = u;
    int k;
    vis[u] = true;
    for (k=head[u]; k!=-1; k=edge[k].next)
    {
        if (!vis[edge[k].to)
        {
            LCA(edge[k].to);
            p[edge[k].to] = u;
        }
    }
    
    for (k=qhead[u]; k!=-1; k = qedge[k].next)
    {
        if (vis[qedge[k].to])
        {
            qedge[k].lca = Find(qedge[k].to);
            qedge[k^1].lca = qedge[k].lca;
        }
    }
}



你可能感兴趣的:(图论基础)