无权图的最短路径

无权图的最短路径

请添加图片描述

Approach:

  • 一种解决方案是使用Bellman-Ford算法在 O(VE) 时间内求解。
  • 如果没有负权重环的话,那么可以使用Dijkstra 算法在 O(E + VLogV) 时间内求解。
  • 由于图是无权的,可以在 O(V + E) 时间内解决这个问题。这个想法是使用广度优先搜索的修改版本,其中我们在进行广度优先搜索时继续存储给定顶点的predecessor。即使图中存在负权重环,该算法也可以完成。
  • 我们首先初始化一个数组 dist[0, 1, …, v-1] ,使得 dist[i] 存储顶点 i源顶点source的距离
  • 数组 pred[0, 1, …, v-1],使得 pred[i] 表示从源开始的广度优先搜索中顶点 i 的直接前驱 immediate predecessor
  • 现在我们在 O(1) 时间内从数组 d 中获得从源顶点source到任何其他顶点的路径长度,并且为了打印从源到任何顶点的路径,我们可以使用数组 p 并且在最坏的情况下将花费 O(V) 时间,因为 V 是数组 P 的大小。所以算法的大部分时间都花在从给定的源顶点source进行广度优先搜索上,我们知道这需要 O(V+E) 时间。因此我们算法的时间复杂度是 O(V+E)

Code:

import java.util.*;

public class ShortestPath {

    static class _1st {

    }


    private static void addEdge(List<List<Integer>> adj, int u, int v) {
        adj.get(u).add(v);
        adj.get(v).add(u);
    }

    /**
     * @param adj  邻接表
     * @param src  源点
     * @param dest 终点
     * @param V    顶点的个数
     */
    public static void printShortestDistance(List<List<Integer>> adj, int src, int dest, int V) {
        int[] dist = new int[V];
        int[] pred = new int[V];
        if (!bfs(adj, src, dest, V, pred, dist)) {
            System.out.println("Given source and destination are not connected");
            return;
        }
        List<Integer> path = new ArrayList<>();
        int cur = dest;
        path.add(cur);
        while (pred[cur] != -1) {
            path.add(pred[cur]);
            cur = pred[cur];
        }
        // Print distance
        System.out.println("Shortest path length is: " + dist[dest]);
        // Print path
        System.out.println("Path is ::");
        for (int i = path.size() - 1; i >= 0; i--) {
            System.out.print(path.get(i) + " ");
        }
    }


    private static boolean bfs(List<List<Integer>> adj, int src, int dest, int V, int[] pred, int[] dist) {
        //存顶点的邻接点将要被访问的
        Queue<Integer> queue = new LinkedList<>();
        //记录当前节点至少被访问过一次
        boolean[] vis = new boolean[V];
        //初始化dist 和 pred 初始距离为MAX 直接前驱节点初始化为-1 不存在的节点
        Arrays.fill(dist, Integer.MAX_VALUE);
        Arrays.fill(pred, -1);
        //src点作为起始点开始转bfs遍历
        vis[src] = true;
        dist[src] = 0;
        queue.offer(src);
        while (!queue.isEmpty()) {
            int u = queue.poll();
            for (int v : adj.get(u)) {
                if (!vis[v]) {//u相邻的节点v,v没有被访问过
                    vis[v] = true;
                    dist[v] = dist[u] + 1;
                    pred[v] = u;
                    queue.offer(v);//当前的节点v的直接前驱节点修改为u
                    if (v == dest) return true;//找到了
                }
            }
        }
        return false;
    }


    public static void main(String args[]) {
        // No of vertices
        int V = 8;
        // Adjacency list for storing which vertices are connected
        List<List<Integer>> adj = new ArrayList<>();
        for (int i = 0; i < V; i++) {
            adj.add(new ArrayList<>());
        }
        // Creating graph given in the above diagram.
        // add_edge function takes adjacency list, source
        // and destination vertex as argument and forms
        // an edge between them.
        addEdge(adj, 0, 1);
        addEdge(adj, 0, 3);
        addEdge(adj, 1, 2);
        addEdge(adj, 3, 4);
        addEdge(adj, 3, 7);
        addEdge(adj, 4, 5);
        addEdge(adj, 4, 6);
        addEdge(adj, 4, 7);
        addEdge(adj, 5, 6);
        addEdge(adj, 6, 7);
        int source = 0, dest = 7;
        printShortestDistance(adj, source, dest, V);
        /**
         * Shortest path length is: 2
         * Path is ::
         * 0 3 7
         */
    }

}

Reference

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值