Tarjan求强联通分量以及Tarjan O(m+n)求LCA

来源:互联网 发布:淘宝产品打折功能收费 编辑:程序博客网 时间:2024/05/21 07:11

Preface

一开始以为Tarjan是个很高级的东西,结果学了一发,发现Tarjan异常的好打,也不是很难理解.

强联通分量O(m)

  • 来一发定义:

    • 强联通分量的定义是:一个强联通分量里的任意两个点都可以互相到达,且是这个图里的极大强联通子图.
  • 具体的算法步骤如下:

  • dfn[x]表示访问x这个节点的编号

  • low[x]表示x可以到达的节点j1,j2,jk中最小的dfn[ji]

  • vis[x]表示当前点x是否还在栈中

  • Maintain

    • 每次当有dfn[x]==low[x]时,从栈顶到x这一段,便组成一个强联通分量.
void Tarjan(int k){    dfn[k] = ++dfsnum, low[k] = dfsnum, d[++top] = k;    for (int x = last1[k]; x; x = next1[x])    {        if (!dfn[tov1[x]]) Tarjan(tov1[x]);        if (!vis[tov1[x]]) low[k] = min(low[k],low[tov1[x]]);    }    if (dfn[k]==low[k])    {        ++cnt;        while (d[top+1] != k) vis[d[top--]] = true;    }}

Tarjan求LCA.

  • 其实这个更简单,也就是记录一个fa[i].

  • 表示这个节点是否到达过.

  • 并且它的父亲是什么(两重含义)

  • 那么,每次到达一个点i,看看与它要求的lca的所有fa[i]是否求过,如果求过,那么就一直往上跳,直到不能跳为止,那个点即为LCA.

  • 具体的证明就很简单了,随便画一画就知道这是对的,O(n+Q)

原创粉丝点击