Tarjan 算法:(求图的联通分量)
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
public class Tarjan {
Stack<Integer> stack=new Stack<Integer>();
boolean[] isVisited;
int[] DFN;
int[] LOW;
int count=0;
List<List<Integer>> output=new ArrayList<List<Integer>>();
public void tarjan(int x,HashMap<Integer,HashSet<Integer>> graph){
DFN[x]=LOW[x]=count++;
isVisited[x]=true;
stack.push(x);
HashSet<Integer> set=graph.get(x);
for(int k:set){
if(!isVisited[k]){
tarjan(k, graph);
LOW[x]=Math.min(LOW[x], LOW[k]);
}else if(stack.contains(k)){
LOW[x]=Math.min(LOW[x], DFN[k]);
}
}
if(LOW[x]==DFN[x]){
List<Integer> one=new ArrayList<Integer>();
int top=0;
do{
top=stack.pop();
one.add(top);
}while(top!=x);//是对x的递归结束时 拿到的以x为根的这个决策树上所有点组成的连通分量
output.add(one);
}
}
public static void main(String[] args) {
int n=6;
int[][] input={
{1,3},
{1,2},
{2,4},
{3,4},
{3,5},
{4,6},
{4,1},
{5,6},
};
HashMap<Integer, HashSet<Integer>> graph=new HashMap<Integer, HashSet<Integer>>();
Tarjan t=new Tarjan();
for(int i=0;i<n;i++){
graph.put(i,new HashSet<Integer>());
}
for(int i=0;i<input.length;i++){
graph.get(input[i][0]-1).add(input[i][1]-1);
}
t.isVisited=new boolean[n];
t.LOW=new int[n];
t.DFN=new int[n];
for(int i=0;i<n;i++){
if(!t.isVisited[i]){
t.tarjan(i, graph);
}
}
System.out.println(t.output);
}
// input:
// 6 8
// 1 3
// 1 2
// 2 4
// 3 4
// 3 5
// 4 6
// 4 1
// 5 6
}