码迷,mamicode.com
首页 > 编程语言 > 详细

【图论】TarjanLCA算法

时间:2021-01-16 12:11:10      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:加速   访问   code   ==   路径   tin   str   倍增lca   数组   

算法的原理:把dfs的点分为三类:

vis[u]=0 表示这个点从未访问
vis[u]=1 表示这个点在栈中,是u点的祖先
vis[u]=2 表示这个点已经退栈

Tarjan算法把lca(x,y)的查询丢给x和y的查询数组记录。后序遍历,总是会先遍历y再遍历x,那么vis[y]=2,要么x是y的祖先,要么是x的某个祖先是y的祖先。这里套个并查集加速一下,对于每个退栈的节点,把它(以及它的子树当然也是退栈了的)合并到其父亲上,那么在查询y在并查集中的代表元素中,会恰好查到还在栈中的那个最深的x的祖先,这个恰好就是lca了。

const int MAXN = 200000 + 10;
const int MAXM = 2000000 + 10;
int n, m;
vi G[MAXN];

int vis[MAXN];
int fa[MAXN];
int ans[MAXN];
struct Query {
    int x, y, id;
} query[MAXN];

void Init() {
    for(int i = 1; i <= n; ++i) {
        G[i].clear();
        vis[i] = 0;
        fa[i] = 0;
    }
    for(int i = 1; i <= n - 1; ++i) {
        int u, v;
        G[u].eb(v);
        G[v].eb(u);
    }
}

void dfs(int u) {
    vis[u] = 1;
    for(int v : G[u]) {
        if(vis[v])
            continue;
        dfs(v);
        fa[v] = u;
    }
    for(Query q : query[u]) {
        int x = q.x, y = q.y, id = q.id;
        if(vis[y] == 2) {
            int lca = getFa(y);
            ans[id] = lca;
        }
    }
    vis[u] = 2;
}

仔细一看觉得这个甚至比倍增LCA还要更好写一些?倍增LCA可以找x和y路径上的最小值,Tarjan怎么找。

【图论】TarjanLCA算法

标签:加速   访问   code   ==   路径   tin   str   倍增lca   数组   

原文地址:https://www.cnblogs.com/purinliang/p/14284957.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!