实验:强连通分量

强连通分量定义:
有向图强连通分量:
对于任意两个不同的顶点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<Integer> diedIndexs;// 存死端节点
static ArrayList<Integer> connectedIndexs;// 强连通分量节点

public static void main(String[] args) {
    // printfMap(matrix);
    diedIndexs = new ArrayList<Integer>();
    connectedIndexs = new ArrayList<Integer>();
    ArrayList<Integer> order = new ArrayList<Integer>();
    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<Integer> 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<Integer> order,
        ArrayList<Integer> 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<Integer> 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();
    }
}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值