zoukankan      html  css  js  c++  java
  • 【转】【模板】求割点和桥

    【要求】给定一个无向图,找出图中的割点个桥

    【说在前面】看了这么多,想入门理解的话真心推荐“听雨草堂”这一篇,结合模板以及各数组表示的含义看,至少把我看懂了。          模板我没用她的,用的是上交红书的模板,反正都一样的东西;

    【几个定义】

      

    • DFS搜索树:用DFS对图进行遍历时,按照遍历次序的不同,我们可以得到一棵DFS搜索树,如图(b)所示。
    • 树边:(或称父子边),在搜索树中的实线所示,可理解为在DFS过程中访问未访问节点时所经过的边。
    • 回边:(或称返祖边后向边),在搜索树中的虚线所示,可理解为在DFS过程中遇到已访问节点时所经过的边。

    【重点】基于DFS的算法 ---> Tarjan

    1. 对根节点u,若其有两棵或两棵以上的子树,则该根结点u为割点;
    2. 对非叶子节点u(非根节点),若其子树的节点均没有指向u的祖先节点的回边,说明删除u之后,根结点与u的子树的节点不再连通;则节点u为割点。

      cur是割点的条件:①cur是根且有大于一个儿子;  ②cur不是根且cur有一个儿子v使low[v] >= dfn[cur];、
      (cur, i)是桥的条件:low[i] > dfn[cur];

    【难点】 对于dfn[MAX_V]与low[MAX_V]数组的理解与模拟其实现过程;

    int dfn[MAX_V]; //结点v被访问时的深度
    int low[MAX_V]; //结点v可以到达的访问时间最早的祖先的深度

     详细示例见原博主;

    【模板】

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<vector>
     5 #include<iostream>
     6 using namespace std;
     7 const int MAX_V = 1000;
     8 const int MAX_E = 1000000;
     9 
    10 int vis[MAX_V]; //结点v当前访问状态,0表示未访问,1表示在栈中,2表示已经访问过
    11 int dfn[MAX_V]; //结点v被访问时的深度
    12 int low[MAX_V]; //结点v可以到达的访问时间最早的祖先的深度
    13 bool cut[MAX_V];
    14 bool bridge[MAX_V][MAX_V];
    15 //cur是割点的条件:①cur是根且有大于一个儿子; ②cur不是根且cur有一个儿子v使low[v]>=dfn[cur];
    16 //(cur, i)是桥的条件:low[i] > dfn[cur];
    17 void cur_bridge(int cur, int father, int dep, int n) //vertex: 0~n-1
    18 {
    19     vis[cur] = 1;
    20     dfn[cur] = dep;
    21     low[cur] = dep;
    22     int children = 0;
    23     for(int i = 0; i < n; i++)
    24     {
    25         if(edge[cur][i]) //与当前节点相连的结点i
    26         {
    27             if(i != father && vis[i] == 1) //i在当前栈中,说明图中有一个环,用i的深度更新cur的low值;
    28             {
    29                 if(dfn[i] < low[cur]) low[cur] = dfn[i]; //将结点cur可以到达的访问时间最早的祖先的深度更新为结点i被访问时的深度;
    30             }
    31             if(vis[i] == 0) //i没被访问过,递归访问节点i,并用i的可以到达的最早祖先来更新cur的low值;
    32             {
    33                 cut_bridge(i, cur, dep+1, n);
    34                 children ++;
    35 
    36                 if(low[i] < low[cur]) low[cur] = low[i];
    37                 if((father == -1 && children > 1) || (father == -1 && low[i] >= dfn[cur]) //判断割点
    38                    cut[cur] = true;
    39                 if(low[i] > dfn[cut]) bridge[cur][i] = bridge[i][cur] = true;             //判断桥
    40             }
    41         }
    42     }
    43     vis[cur] = 2;
    44 }
  • 相关阅读:
    003_cd pushd popd三个命令的区别
    002_更新Nginx证书
    001_nginx常用参数查询
    001_shell经典案例
    001_chrome工具详解
    002_分布式搜索引擎Elasticsearch的查询与过滤
    004_加速国内docker源下载速度
    dango models and database ---- relation ship
    dango models and database ---- verbose name
    MySQL字符集详解
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4728506.html
Copyright © 2011-2022 走看看