快来踩爆这个蒟蒻吧|

Little_corn

园龄:1年1个月粉丝:10关注:17

2024-04-25 13:00阅读: 84评论: 0推荐: 0

强连通分量

定义:

强连通指的是对于一个有向图,每个点都有路径到另外一个点。

强连通分量则指的是对于一个图,它的极大强连通子图。

tanjan 求法:

对于一个图,考虑他的 dfs 生成树(即为对原图进行 dfs 的一棵树)。

那么对于这棵树,搜索时会出现四种边:

树枝边:搜索到没被访问过的节点,且在树中当前节点的直接儿子

前向边:搜索到没被访问的节点,但在树中当前节点的间接儿子

横叉边:搜索到已访问到的节点,但不是当前节点的祖先

返祖边:搜索到已访问的节点,且当前节点的祖先


性质: 如果 u 是一个强连通分量中的第一个访问到的节点,那么其余节点一定是在搜索树中 u 的子树中。

证明: 反证法即可。


那么现在我们考虑到达 u 节点的时间戳,即为 u 是第几个到达的。这里记作 dfn[u].

在回溯的过程中,维护一个栈,用于存储待处理的节点。

再考虑在以 u 为根的子树中能到达的最早的在栈中的节点的时间戳。这里记作 low[i].

那么对于没被访问的节点,有 low[u]=min(low[u],low[v])

对于访问过的且在栈中的节点,有 low[u]=min(low[u],dfn[v])

其他情况对 low[u] 均无贡献。

那么当 low[u]=dfn[u] 时,就表示所有在以 u 为根的子树中 low 值等于 low[u] 的节点组成的图已经满足了极大性和强连通性

且因为以 u 为根的子树中 low 值不等于 low[u] 的节点已经处理完了,所以这个栈中在 u 上的节点的 low 值都等于 low[u] ,此时他们就组成了一个强连通分量

代码:

void tarjan(int u){
dfn[u]=low[u]=++dfnnow;
vis[u]=true;
st[++top]=u;
in_st[u]=true;
for(int i=head[u];i;i=edges[i].next){
int v=edges[i].v;
if(!vis[v]){
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(in_st[v]){
low[u]=min(low[u],dfn[v]);
}
}
if(dfn[u]==low[u]){
scc++;
while(st[top]!=u){
siz[scc]++;
in_st[st[top]]=false;
col[st[top]]=scc;
top--;
}
siz[scc]++;
in_st[st[top]]=false;
col[st[top]]=scc;
top--;
}
return;
}

本文作者:Little_corn

本文链接:https://www.cnblogs.com/little-corn/p/18157430

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Little_corn  阅读(84)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起