zoukankan      html  css  js  c++  java
  • tarjan 割点 割边

    by   GeneralLiu 

    tarjan 求 割点 割边

    无向图  的 割点 割边:

    对于无向连通图来说,
      如果删除   一个点以及与它相连的边   之后,
        使得这个图不连通,
        那么该点为割点 ;
      如果删除 一条边 之后 ,
        使得这个图不连通,
        那么该边为割边 ;
     

    tarjan 是基于 dfs树 的算法

    所以, dfs树 上的一些 术语有必要知道 一下 

    so  看我 博客   

    与 有向图的tarjan算法 非常类似

    割边 的 求法 (这个一步就判断出来,先写容易的):

      在 dfs树 上 后向边 一定不是 割边

        如果是 树边(from u,to v) // 对应 下文 代码 20 行

          且  low [ v ] > dfn [ u ]  // 对应 下文 代码 24,25 行

          则 是割边  

    在 无向图 这里 边的类型只有这两种(没有横叉边前向边

    割点 的 求法

      如果是 dfs树 的 根节点

        且 有不止一个儿子 则 是割点   // 对应 下文 代码 33,34 行

      不是根 

        如果 u 存在子节点 v   // 对应 下文 代码 28,29 行

          使 low[v] >= dfn[u]

          那么u为割点

     

    代码 

     与 有向图的tarjan代码 非常类似

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 #define N 1000
     5 #define M 2000
     6 int dfn[N],low[N],cnt,n,m,head[N],to[M],next[M];
     7 bool cutnode[N],cutedge[M];
     8 void add(int x,int y){
     9     next[++cnt]=head[x];
    10     to[cnt]=y;
    11     head[x]=cnt;
    12 }
    13 void dfs(int fa,int u){
    14     dfn[u]=low[u]=++cnt;
    15     int v,ch=0;
    16     bool b=0;
    17     for(int i=head[u];i;i=next[i]){
    18         v=to[i];
    19         if(v==fa)continue;
    20         if(!dfn[v]){ // 树边
    21             ch++;
    22             dfs(u,v);
    23             low[u]=min(low[u],low[v]);
    24             if(low[v]>dfn[u])  // 判断 割边
    25                 cutedge[(i+1)>>1]=1;  // 无向图边存了两遍 如此来定位 边的编号 
    26         }
    27         else low[u]=min(low[u],dfn[v]);
    28         if(low[v]>=dfn[u]) // 判断 割点
    29             b=1;
    30     }
    31     if(dfn[u]!=1) // 讨论 u 是否 为根 分别处理
    32         cutnode[u]=b;
    33     else if(ch>=2)
    34         cutnode[u]=1;
    35 }
    36 int main(){
    37     scanf("%d%d",&n,&m);
    38     for(int x,y,i=1;i<=m;i++){
    39         scanf("%d%d",&x,&y);
    40         add(x,y);
    41         add(y,x);
    42     }
    43     for(int i=1;i<=n;i++)
    44         if(!dfn[i])
    45             cnt=0,dfs(0,i);
    46     for(int i=1;i<=n;i++) // 输出 割点
    47         if(cutnode[i])
    48             printf("%d ",i);
    49     printf("
    ");
    50     for(int i=1;i<=m;i++) // 输出 割边
    51         if(cutedge[i])
    52             printf("%d ",i);
    53     return 0;
    54 }
  • 相关阅读:
    [转帖]一些理念,一份感动,一段友谊。或许在短暂的一生中就弥足珍贵了。
    浏览器屏蔽双击选中文字
    RBAC: 基于角色的访问控制(Role-Based Access Control)
    关于ehcache配置中timeToLiveSeconds和timeToIdleSeconds的区别
    拓展jQuery的方法
    用HashSet存储不重复的对象
    spring task 实现定时执行(补充:解决定时任务执行2次问题)
    CronExpression
    java使用POI实现excel文件的读取,兼容后缀名xls和xlsx
    jquery的原理机制
  • 原文地址:https://www.cnblogs.com/1227xq/p/6825208.html
Copyright © 2011-2022 走看看