2013 711 sakai keiichikochitech ac jp http www

  • Slides: 15
Download presentation
アルゴリズムとデータ構造 2013年 7月11日 酒居敬一(sakai. keiichi@kochi-tech. ac. jp) http: //www. info. kochi-tech. ac. jp/k 1

アルゴリズムとデータ構造 2013年 7月11日 酒居敬一(sakai. keiichi@kochi-tech. ac. jp) http: //www. info. kochi-tech. ac. jp/k 1 sakai/Lecture/ALG/2013/index. html

public class Biconnected<E> { private int sequence; private int visit(Node<E> node){ node. set. Sequence(++this.

public class Biconnected<E> { private int sequence; private int visit(Node<E> node){ node. set. Sequence(++this. sequence); 隣接する未訪問の頂点に関しては、 int min = this. sequence; 深さ優先探索なので探索する。 for(Node<E> neighbor: node. get. Edges()){ その結果、訪問順が付けられる。 if(neighbor. get. Sequence() == 0){ int m = visit(neighbor); min = Math. min(min, m); 根の子が2個以上(順序数が2より大きい) boolean artic; ときは、根が関節点。 if (node. get. Sequence() == 1) { artic = (neighbor. get. Sequence() != 2); } else { 自分(node)の子から、祖先への逆辺 artic = (m >= node. get. Sequence()); がなければ、自分は関節点。 } if(artic) System. out. println("頂点" + node. get. Value() + "は関節点"); } else if (neighbor. get. Sequence() < min){ min = neighbor. get. Sequence(); } 隣接する訪問済みの頂点に関しては、 } より祖先へ向かう辺(逆辺含む)の先の return min; 頂点の順序数を保持する。 } public void search(Node<E> start){ this. sequence = 0; visit(start); 深く探索していく過程で、より祖先寄りの祖先への逆辺を } 調べながら進んでいる。 7 }

F A public static void main(String[] args) { System. out. println("図 4. 4. 2");

F A public static void main(String[] args) { System. out. println("図 4. 4. 2"); for(Node<Character> node: test_data 2){ node. reset(); } node. A. connect(node. C); node. A. connect(node. D); E node. B. connect(node. C); node. B. connect(node. D); node. C. connect(node. E); H node. D. connect(node. F); node. D. connect(node. G); node. F. connect(node. G); node. E. connect(node. H); node. E. connect(node. I); new Biconnected<Character>(). search(node. A); } D G C B I 図 4. 4. 2 頂点Dは関節点 頂点Eは関節点 頂点Cは関節点 8

public class Strong. Component<E> { private int sequence; 訪問順seq private Stack<Node<E>> stack = new

public class Strong. Component<E> { private int sequence; 訪問順seq private Stack<Node<E>> stack = new Stack<Node<E>>(); private int visit(Node<E> node){ 教科書のlowlink node. set. Sequence(++this. sequence); int min = this. sequence; stack. push(node); 未訪問の場合は探索を進める。 for(Node<E> neighbor: node. get. Edges()){ int m; if(neighbor. get. Sequence() == 0) m = visit(neighbor); else m = neighbor. get. Sequence(); 隣の頂点が訪問済みの場合は、 min = Math. min(min, m); そこからたどれる最も根に } 近い頂点の訪問順を更新する。 if(min == node. get. Sequence()){ Node<E> component; 訪問済みなので木の辺じゃない。 do { component = stack. pop(); System. out. print(component. get. Value() + " "); 深さ優先探索し終わった後、 component. set. Sequence(Integer. MAX_VALUE); 調べてみたら、 } while (component != node); 強連結成分の根だった System. out. println(); (seq=lowlink) } return min; 交差辺経由で探索されないようにする。 この根からつながる } 強連結成分を取り出す。 public void search(Collection<Node<E>> graph){ this. sequence = 0; this. stack. clear(); 12 for(Node<E> node: graph) if(node. get. Sequence() == 0) visit(node); }}

public static void main(String[] args) { System. out. println("図 4. 4. 9"); for(Node<Character> node:

public static void main(String[] args) { System. out. println("図 4. 4. 9"); for(Node<Character> node: test_data 2){ node. reset(); } node. A. connect. To(node. B); node. A. connect. To(node. C); node. B. connect. To(node. E); node. B. connect. To(node. F); node. C. connect. To(node. G); node. D. connect. To(node. A); node. E. connect. To(node. D); D node. E. connect. To(node. H); node. F. connect. To(node. E); node. G. connect. To(node. H); node. H. connect. To(node. I); node. I. connect. To(node. H); new Strong. Component<Character>(). search(test_data 2); } 図 4. 4. 9 I H G C F D E B A A B E C F G H I 図 4. 4. 9 プログラムの実行例 (実線は木の辺、点線はそれ以外の辺) 13