zoukankan      html  css  js  c++  java
  • 寻找无向连通图的割点

    无向连通图的割点又被成为关节点(articulation point), 移除关节点,则原连通图变成两个连通分量, 一个没有关节点的连通图被成为重连通图 (biconnected graph)

    要寻找无向连通图中所有的关节点,比较便捷的方法是利用一次深度优先遍历,找到所有关节点

    对于节点u,及其子节点v,  u->v, 可以用数组dfn[u]来表示当前u的遍历序列号,用low[u]表示u及u的子节点通过非tree edge所能找到的最早的祖先节点的序列号, 如果u是关节点,则有两种情况:

    1. 如果u是根节点,且u有两棵及以上的子树,则节点u为关节点,很明显,移除u会使其两棵子树变成不连通的两个连通分量

    2. 如果对于节点v, low[v]的值 >= dfn[u], 说明v及其子节点最多能指到节点u, 没有其他路径能指到u的祖先,则移除u,其子节点v会成为独立的连通分量

    得到公式:  low[u] = min (

              dfn[u],

              low[v],  u -> v 是tree edge, 即节点v以前未被dfs遍历过, 此时low[u] = min(low[u], low[v])

              dfn[v],  u -> v 是back edge, 即节点v已经被访问过, 此时low[u] = min(low[u], dfn[v]),

              为什么不是low[v]而是dfn[v], 因为此时节点v已经被访问过了,说明 u->v是条回边,v是当前节点u的祖先,我们直接取该祖先的遍历序列值即可

                )

    下表给出图(a)对应的dfn与low数组值。

    i0123456789101112
    vertex A B C D E F G H I J K L M
    dfn[i] 1 5 12 10 11 13 8 6 9 4 7 2 3
    low[i] 1 1 1 5 5 1 5 5 8 2 5 1 1
     1 package com.rui.microsoft;
     2 
     3 public class Test39_FindCutPoints {
     4 
     5     public static void main(String[] args) {
     6         UndirectedGraph dGraph = new UndirectedGraph(5);
     7         dGraph.addEdge(0, 1);
     8         dGraph.addEdge(1, 2);
     9         dGraph.addEdge(2, 0);
    10         dGraph.addEdge(0, 3);
    11         dGraph.addEdge(3, 4);
    12         dGraph.tarjan(0);
    13         
    14         for(int i = 0; i < dGraph.V; i++){
    15             if(dGraph.APs[i]){
    16                 System.out.println(" " + i);
    17             }
    18         }
    19     }
    20 }
    21 
    22 class UndirectedGraph{
    23     
    24     int V;
    25     Bag<Integer>[] adj;
    26     
    27     boolean[] visited;
    28     int[] dfn;
    29     int[] low;
    30     int[] parents;
    31     
    32     boolean[] APs;
    33     
    34     int order = 0;
    35     
    36     public UndirectedGraph(int size) {
    37         this.V = size;
    38         this.adj = new Bag[size];
    39         
    40         this.dfn = new int[size];
    41         this.low = new int[size];
    42         this.parents = new int[size];
    43         this.visited = new boolean[size];
    44         this.APs = new boolean[size];
    45         
    46         for(int i = 0; i < size; i++){
    47             this.adj[i] = new Bag<Integer>();
    48             this.parents[i] = -1;
    49             this.APs[i] = false;
    50         }
    51     }
    52     
    53     void addEdge(int from, int to){
    54         adj[from].add(to);
    55         adj[to].add(from);
    56     }
    57     
    58     void tarjan(int u){
    59         dfn[u] = low[u] = ++order;
    60         visited[u] = true;
    61         int childs = 0;
    62         
    63         //dfs
    64         for(int v: this.adj[u]){
    65             if(!visited[v]){
    66                 childs++;
    67                 parents[v] = u;
    68                 tarjan(v);
    69                 
    70                 //after dfs the subtree of v
    71                 low[u] = min(low[u], low[v]);
    72                 
    73                 //check
    74                 if(parents[u] == -1 && childs > 1){
    75                     APs[u] = true;
    76                 }
    77                 
    78                 if(parents[u] != -1 && dfn[u] <= low[v]){
    79                     APs[u] = true;
    80                 }
    81             }else{
    82                 //back edge
    83                 low[u] = min(low[u], dfn[v]);
    84             }
    85         }
    86     }
    87     
    88     int min(int a, int b){
    89         return a<b? a: b;
    90     }
    91 }

    辅助类Bag

     1 package com.rui.microsoft;
     2 
     3 import java.util.Iterator;
     4 import java.util.NoSuchElementException;
     5 
     6 public class Bag<Item> implements Iterable<Item>{
     7     
     8     private Node<Item> first;
     9     private int N;
    10     
    11     private static class Node<Item>{
    12         private Item item;
    13         private Node<Item> next;
    14     }
    15     
    16     public Bag(){
    17         first = null;
    18         N = 0;
    19     }
    20     
    21     public boolean isEmpty(){
    22         return first == null;
    23     }
    24     
    25     public int size(){
    26         return N;
    27     }
    28     
    29     public void add(Item item){
    30         Node<Item> oldFirst = first;
    31         first = new Node<Item>();
    32         first.item = item;
    33         first.next = oldFirst;
    34         N++;
    35     }
    36     
    37     @Override
    38     public Iterator<Item> iterator() {
    39         return new ListIterator<Item>(first);
    40     }
    41     
    42     private class ListIterator<Item> implements Iterator<Item> {
    43         private Node<Item> current;
    44 
    45         public ListIterator(Node<Item> first) {
    46             current = first;
    47         }
    48 
    49         public boolean hasNext()  { return current != null;                     }
    50         public void remove()      { throw new UnsupportedOperationException();  }
    51 
    52         public Item next() {
    53             if (!hasNext()) throw new NoSuchElementException();
    54             Item item = current.item;
    55             current = current.next; 
    56             return item;
    57         }
    58     }
    59     
    60 }
  • 相关阅读:
    UI层复习笔记
    async 的三大返回类型
    用scikit-learn进行LDA降维
    关于解决python线上问题的几种有效技术
    ASP.NET Core MVC/WebAPi 模型绑定探索
    浅谈 Fragment 生命周期
    vue2.0实践的一些细节
    Linux----------Mysql死锁
    Linux----------容器docker file
    Linux----------常用容器命令
  • 原文地址:https://www.cnblogs.com/aalex/p/4956425.html
Copyright © 2011-2022 走看看