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

 

posted on 2015-03-31 19:37  DevinZ  阅读(208)  评论(0编辑  收藏  举报

导航