zoukankan      html  css  js  c++  java
  • [学习笔记] Tarjan算法求桥和割点

    在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥、割点,也是和上篇有博客有类似之处的。

    关于桥和割点:

    桥:在一个有向图中,如果删去一条边,而后这个有向图不再联通,我们便称删去的这条边为有向图的桥。

    割点:在一个有向图中,如果删去一个点,使这个有向图中剩下的点不在联通,我们便称这个点为有向图的割点。

    Tarjan算法原理分析:

    和上文一样的,我们求出一个dfn数组(进行dfs时遍历的顺序),和一个low数组(以u为根的子树中,能连到dfn值最小的节点)。

    求桥:

    对于一个条边u,v(u,v为边的两个端点),如果dfn[u]<=low[v],那么这条边就是桥。因为以v为根的子树中无法通过返祖边(返祖边的定义可以参考我之前的博客)来连到u的祖先,只能通过u,v这条边才能与u的祖先联通,那么也就意味着将着条边删去后,以v为根的子树将不再能与其他点联通,所以这条边就是桥。

    求割点:

    对于一个点u:

                      1、如果它是根,那么假如它只有一个儿子,那么它就不是割点,假如有多个儿子,那么它就是割点。

                      2、如果它不是根,那么假如dfn[u]<=low[v],它就是割点。因为删掉点u以后,v以及v的子树不能到达u的祖先。

    特别注意:     

    在无向图中,不一定需要返祖边来更新low数组,横叉边也一样可以。

    代码:

    var
      next,head,vet,a,dfn,low:array[1..200000]of longint;
      ans,i,n,m,x,y,tot,time,root:longint;
    function min(a,b:longint):longint;
    begin
      if a<b then exit(a) else exit(b);
    end;
    procedure add(x,y:longint);
    begin
      inc(tot);
      next[tot]:=head[x];
      vet[tot]:=y;
      head[x]:=tot;
    end;
    procedure tarjan(u:longint);
    var
      i,v,cnt:longint;
    begin                                 //
      inc(time); i:=head[u]; cnt:=0;
      dfn[u]:=time; low[u]:=time;
      while i<>0 do
      begin
        v:=vet[i];
        if dfn[v]>0 then low[u]:=min(dfn[v],low[u]) else
        begin
          inc(cnt);
          tarjan(v);
          low[u]:=min(low[u],low[v]);
          if ((u<>root)and(dfn[u]<=low[v])or(u=root)and(cnt>1))and(a[u]=0) then
          begin
            inc(ans); a[u]:=1;
          end;
        end;
        i:=next[i];
      end;
    end;
    begin
      read(n,m);
      for i:=1 to m do
      begin
        read(x,y);
        add(x,y); add(y,x);
      end;
      for i:=1 to n do
      begin
        root:=i;
        if dfn[i]=0 then tarjan(i);
      end;
      writeln(ans);
      for i:=1 to n do
        if a[i]=1 then write(i,' ');
      writeln;
    end.
  • 相关阅读:
    第24课 多线程开发
    第23课 装饰器
    第22课 调用外部程序
    第20课 异常处理
    第19课 习题讲解
    第18课 面向对象
    第17课 调试程序
    第16课 pycharm 使用
    第15课 模块与包
    第14课 再识函数
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/9772279.html
Copyright © 2011-2022 走看看