资讯 小学 初中 高中 语言 会计职称 学历提升 法考 计算机考试 医护考试 建工考试 教育百科
栏目分类:
子分类:
返回
空麓网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
空麓网 > 计算机考试 > 软件开发 > 后端开发 > Java

二十四、搜索与图论——堆优化版 Dijkstra算法(单源最短路 + 正权边 + 稀疏图)

Java 更新时间: 发布时间: 计算机考试归档 最新发布

二十四、搜索与图论——堆优化版 Dijkstra算法(单源最短路 + 正权边 + 稀疏图)

堆优化版 Dijkstra算法主要内容

  • 一、基本思路
    • 1、基本概念
    • 2、基本原理流程
  • 二、Java、C语言模板实现
  • 三、例题题解

一、基本思路

1、基本概念

  • 一般用于求解从 1 号点到其他点——单源最短路
  • 基于贪心算法
  • Si 表示当前已确定最短距离的点
  • 有向图与无向图的边增加与之前一直——只需要考虑为有向图即可

2、基本原理流程

  • 此处摘录来自 AcWing-小呆呆

二、Java、C语言模板实现

//Java 模板实现class PII implements Comparable{    int first;    int second;        public PII(int first, int second){        this.first = first;                 // 此处存储的是距离dis        this.second = second;               // 此处存储的是节点编号    }        public int compareTo(PII o){                        // 此处实现了Comparable接口,为了实现小根堆,按照dis进行排序        return Integer.compare(this.first, o.first);    }}    static int N = 150010;    static int INF = 0x3f3f3f3f;    static int idx = 0;    static int[] h = new int[N];    static int[] e = new int[N];    static int[] ne = new int[N];    static int[] w = new int[N];    static int[] dis = new int[N];    static boolean[] st = new boolean[N];    static int n,m;    static int a,b,c;        static void add(int a, int b, int c){        // 使用单链表,每个点下面挂着可以访问的节点        e[idx] = b;        ne[idx] = h[a];        w[idx] = c;             // 此处用的是邻接表进行边权存储,而不是邻接矩阵        h[a] = idx++;    }        static int dijkstra(){        PriorityQueue queue = new PriorityQueue();        // st表示已经确定最短距离的点        // 使用优先队列寻找  可以连接到的+未被确定距离dis(st为true就可直接略过)  的距离最小值        // queue维护当前未在st中标记过且离源点最近的点        // 然后用这个点去更新其他的点,不过只选择最小值更新                dis[1] = 0;                 // 初始化第一个节点为0        queue.add(new PII(0, 1));   // 将第一个节点加入进行其他点(可以和1链接点)的距离更新                while(!queue.isEmpty()){            PII p = queue.poll();           // 小根堆,根节点就是dis的最小值,相当于已经进行了按序依次取出            int temp = p.second;            // 这里取出的是dis最小点的节点编号            int distance = p.first;         // 这里取出的是dis最小点的dis,为了后面更新与比较                        if(st[temp] == true){                   // 如果为ture ,也就是说明这个点已经确定了最短距离                                                    // 后续只需要其他点在能连接到他的时候进行更新即可。                continue;            }else{                st[temp] = true;            }                                    for(int i = h[temp]; i != -1; i = ne[i]){       //遍历当前这个最小点能链接到的点,更新其他点的距离信息                int j = e[i];                               // 存储的是下一个点标号                if(dis[j] > dis[temp] + w[i]){              // 如果用来更新的t点+本身边权 《 dis,那就可以更新了                    dis[j] = dis[temp] + w[i];                    queue.add(new PII(dis[j], j));          // 这时候这个刚更新距离的点,也可以后面用来更新其他点                }            }                                }        if(dis[n] == INF){            return -1;        }                return dis[n];                    }
```cpp// C++语言实现,此处是yxc实现typedef pair PII;int n;      // 点的数量int h[N], w[N], e[N], ne[N], idx;       // 邻接表存储所有边int dist[N];        // 存储所有点到1号点的距离bool st[N];     // 存储每个点的最短距离是否已确定// 求1号点到n号点的最短距离,如果不存在,则返回-1int dijkstra(){    memset(dist, 0x3f, sizeof dist);    dist[1] = 0;    priority_queue, greater> heap;    heap.push({0, 1});      // first存储距离,second存储节点编号    while (heap.size())    {        auto t = heap.top();        heap.pop();        int ver = t.second, distance = t.first;        if (st[ver]) continue;        st[ver] = true;        for (int i = h[ver]; i != -1; i = ne[i])        {            int j = e[i];            if (dist[j] > distance + w[i])            {                dist[j] = distance + w[i];                heap.push({dist[j], j});            }        }    }    if (dist[n] == 0x3f3f3f3f) return -1;    return dist[n];}

三、例题题解

// java题解实现import java.util.*;public class Main{    static int N = 150010;    static int INF = 0x3f3f3f3f;    static int idx = 0;    static int[] h = new int[N];    static int[] e = new int[N];    static int[] ne = new int[N];    static int[] w = new int[N];    static int[] dis = new int[N];    static boolean[] st = new boolean[N];    static int n,m;    static int a,b,c;        static void add(int a, int b, int c){        // 使用单链表,每个点下面挂着可以访问的节点        e[idx] = b;        ne[idx] = h[a];        w[idx] = c;             // 此处用的是邻接表进行边权存储,而不是邻接矩阵        h[a] = idx++;    }        static int dijkstra(){        PriorityQueue queue = new PriorityQueue();        // st表示已经确定最短距离的点        // 使用优先队列寻找  可以连接到的+未被确定距离dis(st为true就可直接略过)  的距离最小值        // queue维护当前未在st中标记过且离源点最近的点        // 然后用这个点去更新其他的点,不过只选择最小值更新                dis[1] = 0;                 // 初始化第一个节点为0        queue.add(new PII(0, 1));   // 将第一个节点加入进行其他点(可以和1链接点)的距离更新                while(!queue.isEmpty()){            PII p = queue.poll();           // 小根堆,根节点就是dis的最小值,相当于已经进行了按序依次取出            int temp = p.second;            // 这里取出的是dis最小点的节点编号            int distance = p.first;         // 这里取出的是dis最小点的dis,为了后面更新与比较                        if(st[temp] == true){                   // 如果为ture ,也就是说明这个点已经确定了最短距离                                                    // 后续只需要其他点在能连接到他的时候进行更新即可。                continue;            }else{                st[temp] = true;            }                                    for(int i = h[temp]; i != -1; i = ne[i]){       //遍历当前这个最小点能链接到的点,更新其他点的距离信息                int j = e[i];                               // 存储的是下一个点标号                if(dis[j] > dis[temp] + w[i]){              // 如果用来更新的t点+本身边权 《 dis,那就可以更新了                    dis[j] = dis[temp] + w[i];				// 注意此处是wi,使用的是temp到j的权重wi进行更新(单链表存)                    queue.add(new PII(dis[j], j));          // 这时候这个刚更新距离的点,也可以后面用来更新其他点                }            }                                }        if(dis[n] == INF){            return -1;        }                return dis[n];                    }        public static void main(String[] args){        Scanner in = new Scanner(System.in);                n = in.nextInt();        m = in.nextInt();                for(int i = 0; i < N; i++){            h[i] = -1;            dis[i] = INF;        }                for(int i = 0; i < m; i++){            a = in.nextInt();            b = in.nextInt();            c = in.nextInt();            add(a,b,c);        }                int result = dijkstra();                System.out.println(result);            }}class PII implements Comparable{    int first;    int second;        public PII(int first, int second){        this.first = first;                 // 此处存储的是距离dis        this.second = second;               // 此处存储的是节点编号    }        public int compareTo(PII o){                        // 此处实现了Comparable接口,为了实现小根堆,按照dis进行排序        return Integer.compare(this.first, o.first);    }}
转载请注明:文章转载自 http://www.konglu.com/
本文地址:http://www.konglu.com/it/1097922.html
免责声明:

我们致力于保护作者版权,注重分享,被刊用文章【二十四、搜索与图论——堆优化版 Dijkstra算法(单源最短路 + 正权边 + 稀疏图)】因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理,本文部分文字与图片资源来自于网络,转载此文是出于传递更多信息之目的,若有来源标注错误或侵犯了您的合法权益,请立即通知我们,情况属实,我们会第一时间予以删除,并同时向您表示歉意,谢谢!

我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2023 成都空麓科技有限公司

ICP备案号:蜀ICP备2023000828号-2