zoukankan      html  css  js  c++  java
  • 看正月点灯笼老师的笔记—BFS和DFS ( 3 )

    从BFS到Dijkstra算法

    视频地址:https://www.bilibili.com/video/av25829980?t=520

    1,代码

    相对正月老师的存图方法,我用的是 链式前向星 方法,存图(如果不懂,并觉的我讲的还不错的话,可以看一下:https://www.cnblogs.com/asdfknjhu/p/12505173.html  )

    由于要用链式前向星,我把 ABC 一律换为 123,但图总体是没变的

    #define _CRT_SECURE_NO_WARNINGS
    #include<stdio.h>
    #include<stdlib.h>
    #include<queue>
    using namespace std;
    #define N 100
    typedef struct  Edge
    {
        int to;
        int w;
        int pre;
    }eg; eg e[N];
    typedef struct node    // 队列里要放的应该是 点的 id 和 distance ,而不是一条边
    {
        int id;
        int dis;
        node(int  a, int b) :id(a), dis(b) {}
        friend bool operator <(const node &a,const node &b)  // < 的重载
        {
            return a.dis > b.dis;
        }
    }st;
    int tot = 0, last[N], vis[N];
    int dist[N], p[N];   // 记录距离和前一个点的 id
    void add(int from, int to, int w)
    {
        tot++;
        e[tot].to = to;
        e[tot].w = w;
    
        e[tot].pre = last[from];
        last[from] = tot;
    }
    void Dijkstra(int start)
    {
        priority_queue <st>q;   // 小于号的重载是对于优先队列 来说
        q.push(st(start, 0));  // 起点为 1
        dist[start] = 0, p[start] = -1;
        while (q.size())
        {
            st vertex = q.top();
            q.pop();
            vis[vertex.id] = 1;  // 出栈的时候标记
    
            for (int i = last[vertex.id]; ~i; i = e[i].pre)  //遍历这个点相邻的边
            {
                st next = { e[i].to,e[i].w + vertex.dis };
                if (vis[next.id] == 0)                //如果下一个点还没有走过
                {
                    if (dist[next.id] > next.dis)    //如果新来的点距离更近 更新 距离和前一个点的 id,
                    {
                        p[next.id] = vertex.id;
                        dist[next.id] = next.dis;
                        q.push(next);
                    }
                }
    
            }
        }
    }
    void show(int end)
    {
        if (p[end] != -1)
            show(p[end]);
        printf("%d ", end);
    }
    int main(void)
    {
        int n; scanf("%d", &n);
        memset(last, -1, sizeof(last));
        memset(vis, 0, sizeof(vis));
        memset(dist, 0x3f, sizeof(dist));
        tot = 0;
    
        while (n--)
        {
            int from, to, w;   // 起点 终点 权值
            scanf("%d%d%d", &from, &to, &w);
            add(from, to, w);
         if (to != from)    add(to,
    from, w); // 无向图 } Dijkstra(1); // 起点 printf("路线:"); show(6); //终点 printf(" 距离:%d ", dist[6]); system("pause"); return 0; } /* 测试数据 8 1 2 5 1 3 1 2 3 2 2 4 1 3 4 4 3 5 8 4 5 3 4 6 6 */

    2,优先队列 的排序是按照 从起点到各点的距离大小

    由于 A->C->B  小于 A->B,所以 到达 B 点 应用 A->C->B 这条路径

    所以 在优先队列后面插一个 (B,3),就可以让原来 (B,5)无效了,因为(B,3)会插队在(B,5)前面

    3,ditance 和 p 数组

    ditance:记录从起点到达各点的最短路径的 距离

    p:记录到达当前点的最短路径上的前一个点的 编号

    4,有点贪心的意思,

    看点 E,因为一直走的是最短的路,所以 ACBDE,这条点较多的较短路径

    才能赶上 ACE这条点较少较长的路径,避免 (E ,8) 点出队之前,(E,7) 点进入队列,成功插队,

    所以,需要标记一个点是否 visted, 是在这个点出栈的时候,而不是入栈的时候

    5,每次 while 之后 队列里的元素

    一个小细节: ②权值5 这一点比 ④权值5 先进的队列,最后是 ④ 排在 ② 前面

    其实,,在画图时才发现,因为有dist数组,所以有无 vis数组 并不影响结果,只是可以减少循环次数

    ========== ========= ======= ======= ====== ===== ==== === == =

    木玉成约  叶迷

    青楼斜影疏,良人如初顾。
    纤手如玉脂,淡妆胜罗敷。
    引君入香堂,言词论今古。
    君心城切切,妾意情楚楚。
    盟定三生约,共谱月下曲。
    岂料鸳鸯棒,分飞相思苦。
    纵有抱柱信,不能容世俗。
    君子世无双,陌上人如玉。
    不能同世生,但求同归土。
  • 相关阅读:
    Mybatis在oracle批量更新
    WebService小记
    java基本排序
    ant使用
    python 集合
    amazon-aws 使用 SNS 发送短信
    Html5+ 开发APP 后台运行代码
    CentOS7 -防火墙
    java 模拟表单方式提交上传文件
    修改pom项目版本 jenkins 关联 shell命令
  • 原文地址:https://www.cnblogs.com/asdfknjhu/p/12538668.html
Copyright © 2011-2022 走看看