publicstaticclassKosarajuSCC{ int n; List<Integer>[] adj;
KosarajuSCC(int n) { this.n = n; this.adj = new ArrayList[n]; for (int i = 0; i < n; i++) { this.adj[i] = new ArrayList<>(); } }
publicvoidaddEdge(int v, int w){ this.adj[v].add(w); }
//正向遍历,以后根序压栈,保证根先出栈 publicvoidfillorder(int v, boolean[] visited, Stack<Integer> s){ visited[v] = true; for (Integer i : this.adj[v]) { if (!visited[i]) { fillorder(i, visited, s); } } s.push(v); }
//reverse 得到反向图 public KosarajuSCC getTranspose(){ KosarajuSCC gv = new KosarajuSCC(this.n); for (int i = 0; i < n; i++) { for (Integer j : this.adj[i]) { gv.adj[j].add(i); } } return gv; }
//DFS打印连通分支 publicvoidDFSUtil(int v, boolean[] visited){ visited[v] = true; System.out.print(v + " "); for (Integer i : adj[v]) { if (!visited[i]) { DFSUtil(i, visited); } } }
//按照Kosaraju算法的步骤执行 publicvoidprintSCCs(){ Stack<Integer> s = new Stack<Integer>(); boolean[] visited = newboolean[this.n]; for (int i = 0; i < n; i++) { visited[i] = false; } //逆后序压栈 for (int i = 0; i < n; i++) { if (!visited[i]) { fillorder(i, visited, s); } } //得到反向图 KosarajuSCC gr = this.getTranspose(); for (int i = 0; i < n; i++) { visited[i] = false; } //依据反向图算可达性 while (!s.empty()) { int v = s.pop(); if (visited[v] == false) { gr.DFSUtil(v, visited); System.out.println(); } } } }
publicGabowSCC(List<ArrayList<Integer>> graph, int numOfNode){ this.graph = graph; this.numOfNode = numOfNode; this.path = new Stack<>(); this.root = new Stack<>(); order = newint[numOfNode]; part = newint[numOfNode];
for (int i = 0; i < graph.get(v).size(); i++) { int next = graph.get(v).get(i); if (order[next] == NO_VISIT) { gabow(next); } elseif (part[next] == NO_VISIT) { while (order[root.peek()] > order[next]) { root.pop(); } } }
if (v == root.peek()) { root.pop(); partNum++; int top; do { top = path.peek(); part[top] = partNum; path.pop(); } while (top != v); } } }