• Depth-First Search (I)


    1. Eulerian Path

      This is my solution to the USACO training problem "fence", which requires to find a Eulerian Path from a given undirected graph. To store the path of a DFS traversal, we can avail ourselves of the Stack generated by dfs recursive function and another Stack we create such that the two Stacks will constitute a Queue, where the finishing order of the visit can be maintained.

     1 import java.io.*;
     2 import java.util.*;
     3 
     4 public class fence {
     5     public static final int NUM = 500;
     6     public static Scanner input;
     7     public static PrintWriter output;
     8     public static Stack<Integer> path;
     9     public static int [][] adjMat;
    10     
    11     public static void dfs(int pos) {
    12         for (int i=0;i<NUM;i++) {
    13             if (adjMat[i][pos]>0) {
    14                 adjMat[i][pos]--;
    15                 adjMat[pos][i]--;
    16                 dfs(i);
    17             }
    18         }
    19         // two Stacks constitute a Queue
    20         path.push(pos);
    21     }
    22     public static void genEulerPath() {
    23         path = new Stack<Integer>();
    24         int start = 0;
    25         for (int i=0;i<NUM;i++) {
    26             int cnt = 0;
    27             for (int j=0;j<NUM;j++) {
    28                 cnt += adjMat[i][j];
    29             }
    30             if ((cnt&1)==1) {
    31                 start = i;
    32                 break;
    33             }
    34         }
    35         dfs(start);
    36         while (!path.isEmpty()) {
    37             // Print the Eulerian Path:
    38             output.println(path.pop().intValue()+1);
    39         }
    40     }
    41     public static void main(String[] args) throws IOException {
    42         adjMat = new int [NUM][NUM];
    43         input = new Scanner(new FileReader("fence.in"));
    44         int edge = input.nextInt();
    45         for (int i=0;i<edge;i++) {
    46             int p = input.nextInt()-1;
    47             int r = input.nextInt()-1;
    48             adjMat[p][r]++;
    49             adjMat[r][p]++;
    50         }
    51         input.close();
    52         output = new PrintWriter(new FileWriter("fence.out"));
    53         genEulerPath();
    54         output.close();
    55     }
    56 }

    2. SCC and Linearization

      As it turns out, a directed graph can always be looked at as a DAG of its Strongly Connected Components, such that we can print those components in a Topological Order. My following code is aimed to shed light on how to do this work:

      1 import java.util.*;
      2 
      3 class AdjList {
      4     // Adjacency List Class:
      5     private class Vert {
      6         public int end; 
      7         public Vert next;
      8     }
      9     
     10     private int num;
     11     private Vert[] vert;
     12     
     13     public AdjList(int num) {
     14         // Generate num vertices:
     15         this.num = num;
     16         vert = new Vert[num];
     17         for (int i=0;i<num;i++) {
     18             vert[i] = new Vert();
     19         }
     20     }
     21     public void insEdge(int p,int r) {
     22         // Insert a directed edge to the graph:
     23         Vert v = new Vert();
     24         v.next = vert[p].next;
     25         v.end = r;
     26         vert[p].next = v;
     27     }
     28     public AdjList transpose() {
     29         // Generated a transpose graph:
     30         AdjList g = new AdjList(num);
     31         for (int i=0;i<num;i++) {
     32             Vert itr = vert[i].next;
     33             while (itr!=null) {
     34                 g.insEdge(itr.end,i);
     35                 itr = itr.next;
     36             }
     37         }
     38         return g;
     39     }
     40     private void dfs(int src,boolean[] vis,Stack<Integer> path) {
     41         // Depth-First Search in a directed graph:
     42         vis[src] = true;
     43         Vert itr = vert[src].next;
     44         while (itr!=null) {
     45             if (!vis[itr.end]) {
     46                 dfs(itr.end,vis,path);
     47             }
     48             itr = itr.next;
     49         }
     50         // two Stacks constitute a Queue
     51         path.push(src);
     52     }
     53     public void solveSCC() {
     54         // Determine all the Strongly Connected Components
     55         //        and print them in a Topological order:
     56         boolean[] vis = new boolean[num];
     57         Stack<Integer> postVis = new Stack<Integer>();
     58         for (int i=0;i<num;i++) {
     59             // do DFS in the original graph in index order
     60             if (!vis[i]) {
     61                 dfs(i,vis,postVis);
     62             }
     63         }
     64         AdjList g = transpose();
     65         for (int i=0;i<num;i++) {
     66             vis[i] = false;
     67         }
     68         Queue<Stack<Integer>> q = new LinkedList<Stack<Integer>>();
     69         while (!postVis.isEmpty()) {
     70             // do DFS in the transpose graph, and the order is determined
     71             //            by the finishing time of the previous DFS
     72             int i = postVis.pop();
     73             if (!vis[i]) {
     74                 Stack<Integer> comp = new Stack<Integer>();
     75                 g.dfs(i,vis,comp);
     76                 q.add(comp);    // linearization
     77             }
     78         }
     79         int cnt = 0;
     80         while (!q.isEmpty()) {
     81             // in the second DFS loop, a SCC c1 will always come into being before
     82             //        another SCC c2 if c1 has a  path towards c2
     83             System.out.print("Component "+(++cnt)+": ");
     84             Stack<Integer> stack = q.poll();
     85             while (!stack.isEmpty()) {
     86                 System.out.print(stack.pop().intValue()+1+" ");
     87             }
     88             System.out.println();
     89         }
     90     }
     91 }
     92 
     93 public class SCC {
     94     public static void main(String[] args) {
     95         Scanner in = new Scanner(System.in);
     96         System.out.println("Vertex Number:");
     97         AdjList g = new AdjList(in.nextInt());
     98         System.out.println("Edge Number:");
     99         int edgeNum = in.nextInt();
    100         System.out.println("List Edges:");
    101         for (int i=0;i<edgeNum;i++) {
    102             g.insEdge(in.nextInt()-1,in.nextInt()-1);
    103         }
    104         in.close();
    105         g.solveSCC();
    106     }
    107 }


      Sample Input and Output:

         


    References:

      1. Cormen, T. H. et al. Introduction to Algorithms [M] .  北京:机械工业出版社, 2006-09

      2. Dasgupta, Sanjoy, Christos Papadimitriou, and Umesh Vazirani. Algorithms[M].北京:机械工业出版社,2009-01-01

  • 相关阅读:
    三数之和
    167
    二分搜索树
    687
    索引堆
    二分查找 leetcode704
    leetcode 56合并区间 java
    leetcode 1046
    堆的数据结构java
    leetcode 493
  • 原文地址:https://www.cnblogs.com/DevinZ/p/4411441.html
Copyright © 2020-2023  润新知