Java——图

概念

图是由顶点和边组成的一种数据结构,我们之前介绍的树形结构中,树的每一个节点就是顶点,顶点与顶点中的连线就是边,也就是说,树是一种特殊的图

图中的边如果有方向,那么这个图就称为有向图,反之则成为无向图

完全图

如果一个无向图中任意两个节点之间有且仅有一条边,那么称这个图为无向完全图,而一个有向图中,任意两个节点间有且仅有方向相反的边,称之为有向完全图

下图中左侧为无向完全图,右侧为有向完全图
在这里插入图片描述

顶点的度

指的是有几条边与该节点关联,如果是完全图的话,那么分为入度和出度,箭头指向该节点的是这个节点的入度,反之为出度

下图中左侧的所有节点的度都是2,右侧所有节点的入度都是2,出度都是2,也即是所有节点的度都是4
在这里插入图片描述

路径

一个节点到另一个节点要走的边称之为路径,如果这些边上有权值(例如一个节点是北京,一个是天津,一个是上海,那么北京到天津的权值和北京到上海的权值是不一样的)
对于无向图,两个节点间的路径长度等于边的个数
对于有向图,两个节点间的路径长度等于所有边的权值之和

回路和环

对于一个路径,如果起点和终点都一样,那么称这个路径为回路,而如果这个路径的长度为一,也就是这个边是自己指向自己,称之为环

在这里插入图片描述
上图中黑色的三条边组成回路,红色的是环

子图

对于图G,如果图G1的节点都属于图G,边都属于图G,则称G1为G的子图
在这里插入图片描述
例如上图,右面的图就是左侧的图的子图

连通图

如果无向图中任意两个节点间都是有一条路径的,则称这个图是连通图

如果有向图中任意两个节点间都是有一条从起始点到终止点的路径,还有一条从终止点到起始点的路径,则称这个图是强连通图

一个连通图的最小连通子图是该图的生成树

图的存储

在计算机中,主要有下面两种方法来存储图

邻接矩阵

使用矩阵(二维数组来存储节点与节点之间的关系)

对于无向图,两个节点之间如果有边,就是1,或者是边的权值,没有就是0,自己和自己是0,因此,无向图的邻接矩阵表示是关于对角线对称的

对于有向图,一个节点如果有指向另一个节点的边,就是1或者是边的权值,否则就是正无穷,自己和自己是0

在这里插入图片描述

代码实现

定义一个最大值代表正无穷

public class Constant {
    public static final int MAX = Integer.MAX_VALUE;
}

import java.util.Arrays;

/**
 * 使用邻接矩阵存储图
 */
public class GraphByMatrix {
    private char[] arrayV;//顶点数组
    private int[][] matrix;//邻接矩阵
    private boolean isDirect;//是否为有向图

    /**
     * @param size 当前矩阵的顶点个数
     * @param isDirect
     */
    public GraphByMatrix(int size, boolean isDirect){
        this.arrayV = new char[size];
        matrix = new int[size][size];
        for (int i = 0; i < size; i++) {
            Arrays.fill(matrix[i],Constant.MAX);
        }
        this.isDirect = isDirect;
    }

    /**
     * 初始化顶点数组
     * @param array
     */
    public void initArrayV(char[] array){
        for (int i = 0; i < arrayV.length; i++) {
            arrayV[i] = array[i];
        }
    }

    /**
     * 添加边
     * @param srcV 起点
     * @param destV 终点
     * @param weight 权值
     */
    public void addEdge(char srcV, char destV, int weight){
        int srcIndex = getIndexOfV(srcV);
        int destIndex = getIndexOfV(destV);

        matrix[srcIndex][destIndex] = weight;

        //无向图的对称位置也有对应的权值
        if(!isDirect){
            matrix[destIndex][srcIndex] = weight;
        }
    }

    /**
     * 获取v顶点的下标
     * @param v
     * @return
     */
    private int getIndexOfV(char v){
        for (int i = 0; i < arrayV.length; i++) {
            if (arrayV[i] == v){
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取顶点的度
     * 有向图为入度+出度
     * @param v
     * @return
     */
    public int getDevOfV(char v){
        int count = 0;
        int srcIndex = getIndexOfV(v);

        //计算出度
        for (int i = 0; i < arrayV.length; i++) {
            if(matrix[srcIndex][i] != Constant.MAX){
                count++;
            }
        }

        //计算入度
        if(isDirect){
            for (int i = 0; i < arrayV.length; i++) {
                if(matrix[i][srcIndex] != Constant.MAX){
                    count++;
                }
            }
        }

        return count;
    }

    private void printGraph() {
        for (int i = 0; i < arrayV.length; i++) {
            System.out.print(arrayV[i] + " ");
        }
        System.out.println();

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if(matrix[i][j] == Constant.MAX){
                    System.out.print("∞ ");
                } else {
                    System.out.print(matrix[i][j] + " ");
                }
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        GraphByMatrix graph = new GraphByMatrix(4,true);
        char[] array = {'A','B','C','D'};

        graph.initArrayV(array);
        graph.addEdge('A','B',1);
        graph.addEdge('A','D',1);
        graph.addEdge('B','A',1);
        graph.addEdge('B','C',1);
        graph.addEdge('C','B',1);
        graph.addEdge('C','D',1);
        graph.addEdge('D','A',1);
        graph.addEdge('D','C',1);

        graph.printGraph();

        System.out.println(graph.getDevOfV('A'));
    }

}

邻接表

使用数组来表示顶点的集合,使用链表来表示边的关系
也就是说,每一个链表中存储了目标顶点所在的下标
在这里插入图片描述
而如果是有向图,那么会存储两个表,一个是入边表,另一个则是出边表

代码实现

import java.util.ArrayList;

/**
 * 使用邻接表存储图
 */
public class GraphByNode {
    static class Node{
        public int src;//起始位置
        public int dest;//目标位置
        public int weight;//权重
        public Node next;

        public Node(int src, int dest, int weight) {
            this.src = src;
            this.dest = dest;
            this.weight = weight;
        }
    }

    public char[] arrayV;//存储顶点
    public ArrayList<Node> edgList;//存储边
    public boolean isDirect;

    public GraphByNode(int size, boolean isDirect){
        this.arrayV = new char[size];
        edgList = new ArrayList<>(size);
        for (int i = 0; i < size; i++) {
            edgList.add(null);
        }
        this.isDirect = isDirect;
    }

    /**
     * 初始化顶点数组
     * @param array
     */
    public void initArrayV(char[] array){
        for (int i = 0; i < arrayV.length; i++) {
            arrayV[i] = array[i];
        }
    }

    /**
     * 添加边
     * @param srcV
     * @param destV
     * @param weight
     */
    public void addEdge(char srcV, char destV, int weight){
        int srcIndex = getIndexOfV(srcV);
        int destIndex = getIndexOfV(destV);
        addEdgeChild(srcIndex,destIndex,weight);

        if(!isDirect){
            addEdgeChild(destIndex,srcIndex,weight);
        }
    }

    private void addEdgeChild(int srcIndex, int destIndex, int weight){
        Node cur = edgList.get(srcIndex);
        while(cur != null){
            if(cur.dest == destIndex){
                return;
            }
            cur = cur.next;
        }

        //之前没有存储过这条边
        //头插法
        Node node = new Node(srcIndex,destIndex,weight);
        node.next = edgList.get(srcIndex);
        edgList.set(srcIndex,node);
    }

    /**
     * 获取v顶点的下标
     * @param v
     * @return
     */
    private int getIndexOfV(char v){
        for (int i = 0; i < arrayV.length; i++) {
            if (arrayV[i] == v){
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取顶点的度
     * @param v
     * @return
     */
    public int getDevOfV(char v){
        int count = 0;
        int srcIndex = getIndexOfV(v);
        Node cur = edgList.get(srcIndex);

        while(cur != null){
            count++;
            cur = cur.next;
        }

        if(isDirect){
            int destIndex = srcIndex;
            for (int i = 0; i < arrayV.length; i++) {
                if(i == destIndex){
                    continue;
                } else {
                    Node pCur = edgList.get(i);
                    while(pCur != null){
                        if(pCur.dest == destIndex){
                            count++;
                        }
                        pCur = pCur.next;
                    }
                }
            }
        }

        return count;
    }

    public void printGraph(){
        for (int i = 0; i < arrayV.length; i++) {
            System.out.println(arrayV[i] + " ->");
            Node cur = edgList.get(i);
            while(cur != null){
                System.out.print(arrayV[cur.dest] + " ->");
                cur = cur.next;
            }
            System.out.println();
        }
    }

    public static void main(String[] args) {
        GraphByNode graph = new GraphByNode(4,true);
        char[] array = {'A','B','C','D'};

        graph.initArrayV(array);
        graph.addEdge('A','B',1);
        graph.addEdge('A','D',1);
        graph.addEdge('B','A',1);
        graph.addEdge('B','C',1);
        graph.addEdge('C','B',1);
        graph.addEdge('C','D',1);
        graph.addEdge('D','A',1);
        graph.addEdge('D','C',1);

        graph.printGraph();
        System.out.println(graph.getDevOfV('A'));
    }
}

全部代码

import java.util.*;

/**
 * 使用邻接矩阵存储图
 */
public class GraphByMatrix {
    private char[] arrayV;//顶点数组
    private int[][] matrix;//邻接矩阵
    private boolean isDirect;//是否为有向图

    /**
     * @param size 当前矩阵的顶点个数
     * @param isDirect
     */
    public GraphByMatrix(int size, boolean isDirect){
        this.arrayV = new char[size];
        matrix = new int[size][size];
        for (int i = 0; i < size; i++) {
            Arrays.fill(matrix[i],Constant.MAX);
        }
        this.isDirect = isDirect;
    }

    /**
     * 初始化顶点数组
     * @param array
     */
    public void initArrayV(char[] array){
        for (int i = 0; i < arrayV.length; i++) {
            arrayV[i] = array[i];
        }
    }

    /**
     * 添加边
     * @param srcV 起点
     * @param destV 终点
     * @param weight 权值
     */
    public void addEdge(char srcV, char destV, int weight){
        int srcIndex = getIndexOfV(srcV);
        int destIndex = getIndexOfV(destV);

        matrix[srcIndex][destIndex] = weight;

        //无向图的对称位置也有对应的权值
        if(!isDirect){
            matrix[destIndex][srcIndex] = weight;
        }
    }

    /**
     * 获取v顶点的下标
     * @param v
     * @return
     */
    private int getIndexOfV(char v){
        for (int i = 0; i < arrayV.length; i++) {
            if (arrayV[i] == v){
                return i;
            }
        }
        return -1;
    }

    /**
     * 获取顶点的度
     * 有向图为入度+出度
     * @param v
     * @return
     */
    public int getDevOfV(char v){
        int count = 0;
        int srcIndex = getIndexOfV(v);

        //计算出度
        for (int i = 0; i < arrayV.length; i++) {
            if(matrix[srcIndex][i] != Constant.MAX){
                count++;
            }
        }

        //计算入度
        if(isDirect){
            for (int i = 0; i < arrayV.length; i++) {
                if(matrix[i][srcIndex] != Constant.MAX){
                    count++;
                }
            }
        }

        return count;
    }

    private void printGraph() {
        for (int i = 0; i < arrayV.length; i++) {
            System.out.print(arrayV[i] + " ");
        }
        System.out.println();

        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if(matrix[i][j] == Constant.MAX){
                    System.out.print("∞ ");
                } else {
                    System.out.print(matrix[i][j] + " ");
                }
            }
            System.out.println();
        }
    }

    /**
     * 广度优先遍历
     * @param v
     */
    public void bfs(char v){
        boolean[] visited = new boolean[arrayV.length]; //close表
        Queue<Integer> queue = new LinkedList<>();
        int srcIndex = getIndexOfV(v);

        queue.offer(srcIndex);
        while(!queue.isEmpty()){
            int top = queue.poll();
            System.out.print(arrayV[top] + "->");
            visited[top] = true;

            for (int i = 0; i < arrayV.length; i++) {
                if(matrix[top][i] != Constant.MAX && visited[i] == false){
                    queue.offer(i);
                    visited[i] = true;
                }
            }
        }
    }

    /**
     * 深度优先遍历
     * @param v
     */
    public void dfs(char v){
        boolean[] visited = new boolean[arrayV.length]; //close表
        int srcIndex = getIndexOfV(v);
        dfsChild(srcIndex,visited);
    }

    private void dfsChild(int srcIndex, boolean visited[]){
        System.out.print(arrayV[srcIndex] + "->");
        visited[srcIndex] = true;
        for (int i = 0; i < arrayV.length; i++) {
            if(matrix[srcIndex][i] != Constant.MAX && visited[i] == false){
                dfsChild(i,visited);
            }
        }
    }

    /**
     * 边的抽象类
     */
    static class Edge{
        public int srcIndex;
        public int destIndex;
        public int weight;

        public Edge(int srcIndex, int destIndex, int weight) {
            this.srcIndex = srcIndex;
            this.destIndex = destIndex;
            this.weight = weight;
        }
    }
    /**
     * 求最小生成子树
     * @param minTree 存储找到的边
     * @return 最小生成树的权值和
     */
    public int kruskal(GraphByMatrix minTree){
        //存储所有的边
        PriorityQueue<Edge> minQ = new PriorityQueue<>(new Comparator<Edge>() {
            @Override
            public int compare(Edge o1, Edge o2) {
                return o1.weight - o2.weight;
            }
        });

        int n = arrayV.length;
        UnionFindSet ufs = new UnionFindSet(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(i < j && matrix[i][j] != Constant.MAX){
                    minQ.offer(new Edge(i, j, matrix[i][j]));
                }
            }
        }

        int size = 0;
        int totalWight = 0;
        while(size < n - 1 && !minQ.isEmpty()){
            Edge edge = minQ.poll();
            int srcIndex = edge.srcIndex;
            int destIndex = edge.destIndex;

            if(!ufs.isSameUnionFindSet(srcIndex,destIndex)){
                minTree.addEdgeUseIndex(srcIndex,destIndex,edge.weight);
                size++;
                totalWight += edge.weight;
                ufs.union(srcIndex, destIndex);
            }
        }

        if(size == n - 1){
            return totalWight;
        } else {
            return -1;
        }
    }

    private void addEdgeUseIndex(int srcIndex, int destIndex, int weight){
        matrix[srcIndex][destIndex] = weight;

        //无向图的对称位置也有对应的权值
        if(!isDirect){
            matrix[destIndex][srcIndex] = weight;
        }
    }

    /**
     * 求最小生成子树
     * @param minTree
     * @param chv 起始点
     * @return
     */
    public int prim(GraphByMatrix minTree, char chv){
        int srcIndex = getIndexOfV(chv);
        //存储已经确定的点
        Set<Integer> setX = new HashSet<>();
        setX.add(srcIndex);

        //存储尚未确定的点
        Set<Integer> setY = new HashSet<>();
        int n = arrayV.length;
        for (int i = 0; i < n; i++) {
            if(i != srcIndex){
                setY.add(i);
            }
        }

        //存储所有的边
        PriorityQueue<Edge> minQ = new PriorityQueue<>(new Comparator<Edge>() {
            @Override
            public int compare(Edge o1, Edge o2) {
                return o1.weight - o2.weight;
            }
        });

        //将所有与起始点有关的边放到优先级队列中
        for (int i = 0; i < n; i++) {
            if(matrix[srcIndex][i] != Constant.MAX){
                minQ.offer(new Edge(srcIndex, i, matrix[srcIndex][i]));
            }
        }

        int size = 0;
        int totalWeight = 0;
        while(!minQ.isEmpty()){
            Edge min = minQ.poll();
            int srcI = min.srcIndex;
            int desT = min.destIndex;

            if(setX.contains(desT)){
                //构成环
            } else {
                minTree.addEdgeUseIndex(srcI, desT, min.weight);
                size++;
                totalWeight += min.weight;
                if(size == n - 1){
                    return totalWeight;
                }
                //更新两个集合中的节点
                setX.add(desT);
                setY.remove(desT);

                //将desT连接的所有边放到minQ
                for (int i = 0; i < n; i++) {
                    if(matrix[desT][i] != Constant.MAX && !setX.contains(i)){
                        minQ.offer(new Edge(desT, i, matrix[desT][i]));
                    }
                }
            }
        }
        return -1;
    }

    public static void testGraphMinTreeKruskal() {
        String str = "abcdefghi";
        char[] array =str.toCharArray();
        GraphByMatrix g = new GraphByMatrix(str.length(),false);
        g.initArrayV(array);
        g.addEdge('a', 'b', 4);
        g.addEdge('a', 'h', 8);
//g.addEdge('a', 'h', 9);
        g.addEdge('b', 'c', 8);
        g.addEdge('b', 'h', 11);
        g.addEdge('c', 'i', 2);
        g.addEdge('c', 'f', 4);
        g.addEdge('c', 'd', 7);
        g.addEdge('d', 'f', 14);
        g.addEdge('d', 'e', 9);
        g.addEdge('e', 'f', 10);
        g.addEdge('f', 'g', 2);
        g.addEdge('g', 'h', 1);
        g.addEdge('g', 'i', 6);
        g.addEdge('h', 'i', 7);
        GraphByMatrix kminTree = new GraphByMatrix(str.length(),false);
        System.out.println(g.kruskal(kminTree));
        kminTree.printGraph();
    }

    public static void testGraphMinTreePrim() {
        String str = "abcdefghi";
        char[] array = str.toCharArray();
        GraphByMatrix g = new GraphByMatrix(str.length(), false);
        g.initArrayV(array);
        g.addEdge('a', 'b', 4);
        g.addEdge('a', 'h', 8);
//g.addEdge('a', 'h', 9);
        g.addEdge('b', 'c', 8);
        g.addEdge('b', 'h', 11);
        g.addEdge('c', 'i', 2);
        g.addEdge('c', 'f', 4);
        g.addEdge('c', 'd', 7);
        g.addEdge('d', 'f', 14);
        g.addEdge('d', 'e', 9);
        g.addEdge('e', 'f', 10);
        g.addEdge('f', 'g', 2);
        g.addEdge('g', 'h', 1);
        g.addEdge('g', 'i', 6);
        g.addEdge('h', 'i', 7);
        GraphByMatrix primTree = new GraphByMatrix(str.length(), false);
        System.out.println(g.prim(primTree, 'a'));
        primTree.printGraph();
    }

    /**
     * 查找两节点最短路径
     * @param vSrc 指定的节点
     * @param dist 距离数组
     * @param pPath 路径
     */
    public void dijkstra(char vSrc, int[] dist, int[] pPath){
        int srcIndex = getIndexOfV(vSrc);
        //初始化距离数组
        Arrays.fill(dist,Constant.MAX);
        dist[srcIndex] = 0;

        //初始化路径数组
        Arrays.fill(pPath,-1);
        pPath[srcIndex] = 0;

        //创建数组,记录当前节点是否被记录
        int n = arrayV.length;
        boolean[] s = new boolean[n];

        //n个顶点
        for (int k = 0; k < n; k++) {
            int min = Constant.MAX; //最小值
            int u = srcIndex; //最小值下标
            for (int i = 0; i < n; i++) {
                if(s[i] == false && dist[i] < min){
                    min = dist[i];
                    u = i;
                }
            }
            s[u] = true;

            //松弛与u有关的所有顶点
            for (int v = 0; v < n; v++) {
                if(s[v] == false && matrix[u][v] != Constant.MAX && dist[u] + matrix[u][v] < dist[v]){
                    dist[v] = dist[u] + matrix[u][v];//更新距离
                    pPath[v] = u;//更新路径
                }
            }
        }
    }

    public void printShortPath(char vSrc, int[] dist, int[] pPath){
        int srcIndex = getIndexOfV(vSrc);
        int n = arrayV.length;

        for (int i = 0; i < n; i++) {
            if(i != srcIndex){
                ArrayList<Integer> path = new ArrayList<>();
                int pathI = i;
                while(pathI != srcIndex){
                    path.add(pathI);
                    pathI = pPath[pathI];
                }
                path.add(srcIndex);
                Collections.reverse(path);

                for (int pos: path){
                    System.out.print(arrayV[pos] + "-> ");
                }
                System.out.println(dist[i]);
            }
        }
    }

    public static void testGraphDijkstra() {
        String str = "syztx";
        char[] array = str.toCharArray();
        GraphByMatrix g = new GraphByMatrix(str.length(),true);
        g.initArrayV(array);
        g.addEdge('s', 't', 10);
        g.addEdge('s', 'y', 5);
        g.addEdge('y', 't', 3);
        g.addEdge('y', 'x', 9);
        g.addEdge('y', 'z', 2);
        g.addEdge('z', 's', 7);
        g.addEdge('z', 'x', 6);
        g.addEdge('t', 'y', 2);
        g.addEdge('t', 'x', 1);
        g.addEdge('x', 'z', 4);
        int[] dist = new int[array.length];
        int[] parentPath = new int[array.length];
        g.dijkstra('s', dist, parentPath);
        g.printShortPath('s', dist, parentPath);
    }

    public boolean bellmanFord(char vSrc, int[] dist, int[] pPath){
        int srcIndex = getIndexOfV(vSrc);
        //初始化距离数组
        Arrays.fill(dist,Constant.MAX);
        dist[srcIndex] = 0;

        //初始化路径数组
        Arrays.fill(pPath,-1);
        pPath[srcIndex] = 0;

        int n = arrayV.length;

        //更新n次
        for (int k = 0; k < n; k++) {
            //遍历矩阵的每一个元素
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if(matrix[i][j] != Constant.MAX && dist[i] + matrix[i][j] < dist[j]){
                        dist[j] = dist[i] + matrix[i][j];
                        pPath[j] = i;
                    }
                }
            }
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(matrix[i][j] != Constant.MAX && dist[i] + matrix[i][j] < dist[j]){
                    //存在负权回路
                    return false;
                }
            }
        }
        return true;
    }

    public static void testGraphBellmanFord() {
        String str = "syztx";
        char[] array = str.toCharArray();
        GraphByMatrix g = new GraphByMatrix(str.length(),true);
        g.initArrayV(array);
        /* g.addEdge('s', 't', 6);
        g.addEdge('s', 'y', 7);
        g.addEdge('y', 'z', 9);
        g.addEdge('y', 'x', -3);
        g.addEdge('z', 's', 2);
        g.addEdge('z', 'x', 7);
        g.addEdge('t', 'x', 5);
        g.addEdge('t', 'y', 8);
        g.addEdge('t', 'z', -4);
        g.addEdge('x', 't', -2);*/
        //负权回路实例
        g.addEdge('s', 't', 6);
        g.addEdge('s', 'y', 7);
        g.addEdge('y', 'z', 9);
        g.addEdge('y', 'x', -3);
        g.addEdge('y', 's', 1);
        g.addEdge('z', 's', 2);
        g.addEdge('z', 'x', 7);
        g.addEdge('t', 'x', 5);
        g.addEdge('t', 'y', -8);
        g.addEdge('t', 'z', -4);
        g.addEdge('x', 't', -2);
        int[] dist = new int[array.length];
        int[] parentPath = new int[array.length];
        boolean flg = g.bellmanFord('s', dist, parentPath);
        if(flg) {
            g.printShortPath('s', dist, parentPath);
        }else {
            System.out.println("存在负权回路");
        }
    }

    public void floydWarShall(int[][] dist, int[][] pPath){
        int n = arrayV.length;
        for (int i = 0; i < n; i++) {
            Arrays.fill(dist[i],Constant.MAX);
            Arrays.fill(pPath[i],-1);
        }

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(matrix[i][j] != Constant.MAX){
                    dist[i][j] = matrix[i][j];
                    pPath[i][j] = i;
                } else {
                    pPath[i][j] = -1;
                }

                if(i == j){
                    dist[i][j] = 0;
                    pPath[i][j] = -1;
                }
            }
        }
        for (int k = 0; k < n; k++) {

            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if(dist[i][k] != Constant.MAX && dist[k][j] != Constant.MAX
                            && dist[i][k] + dist[k][j] < dist[i][j]){
                        dist[i][j] = dist[i][k] + dist[k][j];

                        //更新父节点路径
                        pPath[i][j] = pPath[k][j];
                    }
                }
            }
        }
    }

    public static void main(String[] args) {
        //testGraphMinTree();
        //testGraphMinTreePrim();
        //testGraphDijkstra();
        testGraphBellmanFord();
    }

}

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值