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 }
  • 相关阅读:
    西卡编程教学 C语言教学视频(共32课更新完毕) 『 西卡教学 』 西卡学院 Powered by Pureing Labs!
    大图片新闻的体验还是不错的
    分享:用php抓取网页内容方法总结
    “深圳文献港”昨日正式开通_综合新闻_财经_腾讯网
    分享:EJDB 1.0.37 发布,嵌入式 JSON 数据库引擎
    分享:MetaModel 3.2.5 发布,数据库元模型
    RQ: Simple job queues for Python
    分享:开源主机项目 Ouya 发布 SDK
    RQ 简单的任务队列 品牌控
    信息论、推理与学习算法(翻译版)
  • 原文地址:https://www.cnblogs.com/LLGemini/p/4728506.html
Copyright © 2011-2022 走看看