强连通分量定义:
有向图强连通分量:
对于任意两个不同的顶点u和v,存在一个从u到v的有向路径以及一条从v到u的有向路径,这样的有向图称为是强连通的.一般来说,一个有向图的顶点可以分割成一些顶点互不相交的最大子集,每个子集的顶点之间可以通过有向图中的有向路径互相访问,这些子集被称为强连通分量(strong connected component).
求强连通分量解决办法:
method1:
1. 对图进行深度优先遍历,按顺序输出死端节点
2. 按以上输出结点顺序进行深度优先遍历,每次遍历得到的结点集就是一个强连通分量。
method2:
1. 对图进行拓扑排序,输出排序结果
2. 翻转图中的边
3. 按照排序结果顶点的顺序对图进行深度优先遍历。
另外 , 有两种算法可以验证一个有向图是否是一个无环有向图,又可以在是的情况下,输出拓扑排序的一个顶点序列.
第一种算法 : 执行一次dfs遍历,并记住顶点变成死端的顺序,将该次序反过来就得到拓扑排序的一个解.
第二章算法 : 基于减治技术的一个直接实现,不断在余下的有向图中求出一个源,它是一个没有输入边的顶点,然后把它和所有从它出发的边都删除,顶点被删除的次序就是拓扑排序的一个解.
m1代码:
“`
import java.util.ArrayList;
public class TestDFS {
static int n = 8;
static boolean[] isVisited = new boolean[n];// 记录是否访问过
static char vertexs[] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' };
static int matrix[][] = {
// 有向邻接矩阵表示图 a b c d e f g h
{ 0, 1, 0, 0, 0, 0, 0, 0 }, // a
{ 0, 0, 0, 0, 0, 0, 1, 0 }, // b
{ 0, 0, 0, 1, 1, 0, 0, 0 }, // c
{ 0, 1, 0, 0, 0, 0, 1, 0 }, // d
{ 0, 0, 0, 0, 0, 0, 0, 1 }, // e
{ 1, 1, 0, 0, 0, 0, 0, 0 }, // f
{ 0, 0, 0, 0, 0, 1, 0, 0 }, // g
{ 0, 0, 1, 1, 0, 0, 0, 0 }, // h
};
static ArrayList diedIndexs;// 存死端节点
static ArrayList connectedIndexs;// 强连通分量节点
public static void main(String[] args) {
// printfMap(matrix);
diedIndexs = new ArrayList();
connectedIndexs = new ArrayList();
ArrayList order = new ArrayList();
for (int i = 0; i < n; i++) {
order.add(i);
}
System.out.println("输出死端节点:");
dfsTest(order, diedIndexs);
isVisited = new boolean[n];// 重新初始化
System.out.println("\n输出强连通分量:");
dfsTest(diedIndexs, connectedIndexs);
getStrongConComp(connectedIndexs);
}
// 从v个节点开始深度遍历
public static void search(int v, ArrayList indexlist) {
isVisited[v] = true;
// 打印当前遍历的节点
// 遍历邻接矩阵
for (int u = 0; u < n; ++u) {
if (matrix[v][u] == 1 && isVisited[u] == false) {
search(u, indexlist);
}
}
System.out.print(vertexs[v] + " ");
indexlist.add(v);
}
// 深度优先遍历
public static void dfsTest(ArrayList order,
ArrayList indexlist) {
for (int i = 0; i < n; ++i) {
isVisited[i] = false;
}
for (int i = 0; i < n; ++i) {
if (isVisited[order.get(i)] == false) {
search(order.get(i), indexlist);
}
}
}
// 处理强连通分量结果
public static void getStrongConComp(ArrayList connectedIndexs) {
int flag = 0;
for (int i = 0; i < connectedIndexs.size() + 1; i++) {
if (diedIndexs.subList(flag, i).containsAll(
connectedIndexs.subList(flag, i))) {
// 输出连通分量:
System.out.println("\n连通分量:");
for (int j = flag; j < i; j++) {
System.out.print(vertexs[connectedIndexs.get(j)] + " ");
}
flag = i;
}
}
}
// 打印图
public static void printfMap(int matrix[][]) {
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
if (matrix[i][j] == 1) {
System.out.println(vertexs[i] + " ---> " + vertexs[j]);
}
}
System.out.println();
}
}
}