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