0
点赞
收藏
分享

微信扫一扫

算法补完计划(四)Tarjan算法

技术只适用于干活 2022-04-24 阅读 43

一些概念

割点

无向图中,如果有一个结点x,当我们去掉x结点已经与其相连的边后,该图被分成若干个不相连子图(或者说这个图不联通了),那x即为割点

又叫割边, 如果有一条边edge,我们去掉这条边后,图被分成两个不相连的子图,那这条边就叫做

强连通分量

有向图的极大强连通子图

Tarjan求强连通分量

经典tarjan = _ =,一直学的不大明白,加深一下印象

dfn[x] / low[x]

这俩变量是理解tarjan算法比较重要的东西

dfn[x]是时间戳,这个时间戳的意思就是dfs时访问的顺序

low[x]是x以及x的子树能够追溯到的最早的栈中节点的dfn

(low[]这个概念弄的我一直比较蒙,其实通俗点来说,从x出发,延伸到后面又回到了自己,那肯定是存在一个环的,这个环上的点都是强连通的,add:强连通分量是极大强连通子图

假设从x出发,那我们怎么知道退到x时,它下面的有所有和它构成强连通分量的点呢

开个

如果u下面要遍历的点v已经在栈中了,那low[u] = dfn[v]

如果不在栈中,low[u] = min(low[u],low[v] )

dfn[x] = low[x]说明x是强连通分量的根

代码

void dfs(int u){
    q.push(u);
    in[u] = 1;
    dfn[u] = low[u] = ++Time;//时间戳
    for(int i = head[u]; i; i = edge[i].next){
        int v = edge[i].v;
        if(dfn[v] == 0){
            dfs(v);//没遍历过就继续
            low[u] = min(low[u], low[v]);//回溯的时候更新最小值
        }
        else if(instack[v] == 1){
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u]){
        while(!q.empty()){
            int t = q.top();
            q.pop();
            instack[t] = 0;
			fa[t] = u;
			if(t == u)break;
        }
    }
}

这里染了一下色,令强连通分量中的结点fa都为强连通分量的根结点

割点与桥

有空补。。

举报

相关推荐

0 条评论