首页 > 其他分享 >Tarjan 求有向图的强连通分量

Tarjan 求有向图的强连通分量

时间:2024-06-20 19:11:29浏览次数:15  
标签:Tarjan 有向图 xfa 连通 tp dfn Maxn low

重温Tarjan, 网上看了许多博客感觉都讲的不清楚. 故传上来自己的笔记, 希望帮到大家.

提到的一些概念可以参考 oi wiki, 代码也是 oi wiki 的, 因为我不认为我能写出比大佬更好的代码了.


强连通分量: 有向图的最大强连通子图 ( 有向图中任意两点可达 )

  • Tarjan

    1. 对每个结点维护:

      • dfn[x]: 当前节点的 dfs 序.

      • low[x]: x 向下搜索能到达的最小 dfs 序.

    2. 更新 low:

      1. v 未被访问过: 初始 low[v] = dfn[v].v 入栈. 回溯时用 low[v] 更新它的 fa 的 low[ ].

      2. v 被访问过, 且还在栈中: 用 dfs[v] 更新 fa 的 low.

      3. v 被访问过, 不在栈中: 说明这是一个 fa 到 v 的单向访问, 跳过.

    3. 获取答案:

      能让 dfn[x] > low[x], 只有当 X 的子树中某个节点 C 有\(\begin {cases}1.一条横向边连接到一棵已遍历过的子树~A\\2.一条返祖边连接到~X~的祖先~xfa \end{cases}\) .

      1. 横向边: 说明 A 没有连接到 C 的边, 否则在之前 C 就被遍历了, 轮不到 X 来遍历. 就用是否 C 在栈中来排除这个情况, 子树 A 中的所有强连通分量之前已经出栈过了( 看代码的实现 ).
      2. 返祖边: 说明 xfa -> x -> c -> xfa 形成环, 在同一个强连通子图( 我们知道, 强连通图是许多环嵌套成的 ). 而且这个子图的根是 xfa 满足 dfn[xfa] = low[xfa].

      此时栈中进来过三类节点 :

      \[\begin {cases}1.~在~x~的子树中\begin {cases}1.~属于上述~xfa~循环的,~在同一个强连通子图.\\2.~不在同一个强连通子图,~那递归的讲,~在之前就因为属于某个~xfa'~(在~X~的子树中),而被踢出栈了.\end{cases}\\2. 不在~x~的子树中(即在已遍历过的子树中),~在栈中的位置一定在~x~的下面. \end{cases} \]

      故, 回溯时若节点符合 dfn[x] = low[x], 说明当前节点是它所属连通块的最小节点. 栈里它之上所有点都是一个强连通块.

代码:

 const int Maxn = 1e5 + 10;
    
    int dfn[Maxn], low[Maxn], dfncnt, s[Maxn], in_stack[Maxn], tp;
    int scc[Maxn], sc;  // 结点 i 所在 SCC 的编号
    int sz[Maxn];       // 强连通 i 的大小
    
    void tarjan(int u) {
        low[u] = dfn[u] = ++dfncnt, s[++tp] = u, in_stack[u] = 1;
        for (int i = head[u]; i; i = eg[i].nex) {
            const int &v = eg[i].to;
            if (!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if (in_stack[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if (dfn[u] == low[u]) {
            ++sc;
            while (s[tp] != u) {
                scc[s[tp]] = sc;
                sz[sc]++;
                in_stack[s[tp]] = 0;
                --tp;
            }
            scc[s[tp]] = sc;
            sz[sc]++;
            in_stack[s[tp]] = 0;
            --tp;
        }
    }

标签:Tarjan,有向图,xfa,连通,tp,dfn,Maxn,low
From: https://www.cnblogs.com/taulee01/p/18259333

相关文章

  • 21、docker-网络连通-两个不同网络之间的连通
     语法  测试:dockernetworkconnectmynettomcat-net-01//这里tomcat-net-01容器用的是默认的网络、通过connect连接到了自定义的网络mynet查看mynet网络·连通之后就是将tomcat-net-01放到了mynet网络下 连通之后就可以互相ping通了......
  • 【无线传感器节点部署WSN】使用最陡下降法和遗传算法进行受连通性和覆盖范围约束的无
    ......
  • Tarjan
    开始我最爱的tarjan吧。说一句,Tarjan最难的不是算法学习,而是如何使用。有向图的强连通分量有向图的强连通分量,是指在有向图的一块地方,在这块地方里面,每个点都能互相到达,这就叫做一个强连通分量定义这里是OIwiki上的定义强连通的定义是:有向图G强连通是指,G中任意两个结......
  • 取STL最大连通区域并写入体积信息python实现
    importtrimeshimportnumpyasnpimportargparsefromstlimportMeshdefmain(input_file,output_file,num,volume_info):#加载STL文件your_mesh=trimesh.load_mesh(input_file)#分割成连通域connected_components=your_mesh.split()#......
  • 知识点整理 - 连通性相关 | 《综述图论中连通性及相关问题的一些处理方法》学习笔记
    是ix35老师论文的学习笔记,同时也用作连通性相关知识梳理。可能不会包含很多定义,只会挑重要的写。会包含一些例题。定义与记号\(u\rightsquigarrowv\)代表\(u\)到\(v\)的一条路径。有时也会用这个记号表示连通性。无向图点/边连通度:若\(u,v\)任意点割集大小不小......
  • 有向图的创建以及遍历
    有向图的创建有很多种方法,这里简要介绍邻接表的创建,以及通过邻接表创建的有向图进行深度优先算法以及广度优先算法可以先看看,具体文件的格式,大家想要实现的话,需要在桌面上创建一个txt格式的文件,然后将其命名为linjiebiao57v1v2v3v4v501031423243240文件......
  • LCA(倍增与Tarjan)
    如果我来到了我们的LCA,我是不是就可以假装偶遇你了首先是倍增法,和ST表如出一辙呢。注意N通常在5e5的范围点击查看代码inthead[N],cnt;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(intu,intv){e[++cnt].from=u;e[cnt].to=v;......
  • 图论-割边与边双连通分量
    首先是两篇模板割边点击查看代码inthead[N],cnt=1;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(intu,intv){e[++cnt].from=u;e[cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;}intdfn[N],back[N],tim,bri_cnt;//dfn......
  • 图论-割点与点双连通分量
    首先是两篇的代码割点点击查看代码inthead[N],cnt=0;structEdge{intfrom,to,nxt;}e[N<<1];voidadd(intu,intv){e[++cnt].from=u;e[cnt].to=v;e[cnt].nxt=head[u];head[u]=cnt;}intdfn[N],back[N],tim;//dfn[i]时......
  • 解锁服务器连接状态新姿势:tcping工具助你高效诊断网络连通性
    使用tcping工具检测服务器连接状态在IT运维环境中,由于安全考虑,很多服务器和交换机可能会禁用ICMP(InternetControlMessageProtocol)响应,即“ping”请求,以防止ICMPFLOOD攻击和不必要的资源消耗。然而,运维人员仍需要一种方法来验证与这些服务器的连接状态。在这种情况下,tcping......