zoukankan      html  css  js  c++  java
  • #单源最短路 #Dijkstra 学习心得 20.8.13

    最短路

    最短路学习思路图

    朴素Dijkstra

    链接
    1、思路
    *0、定义数组 dis[n] (从1到其它点的距离), s[n](已经确定最短距离的点);
    *1、初始化 dis[1] = 0, dis[其它点] = 正无穷;
    *2、 for(1 ~ n);——————————循环 n 次,更新所有的点 t;
    *3 找到 不在s中的,距离最近的点 t;
    *4 将t加入s;
    *5 用t更新其它点的距离;————————循环n次
    (这里是两 层 循环, 所以时间复杂度是 n^2)
    *6 返回

    例题
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 510;
    
    int n, m;
    int g[N][N];
    int djs[N];
    bool s[N];
    
    int djst(){
        memset(djs, 0x3f3f3f3f, sizeof djs);				/* *1 */
        djs[1] = 0;											/* *1 */
        
        for(int i = 0; i < n; i ++){						/* *2 */
            int t = -1;										/* *3 */
            for(int j = 1; j <= n; j ++)					/* *3 */
                if(!s[j] && (t == -1 || djs[t] > djs[j]))	/* *3 */ 
                    t = j;									/* *3 */
                
            s[t] = 1;										/* *4 */
            
            for(int j = 1; j <= n; j ++)					/* *5 */
                djs[j] = min(djs[j], djs[t] + g[t][j]);		/* *5 */
        }
        if(djs[n] == 0x3f3f3f3f) return -1;					/* *6 */
        return djs[n];										/* *6 */
    }
    
    int main(){
        cin >> n >> m;
        memset(g, 0x3f3f3f3f, sizeof g);
        while(m --){
            int a, b, c;
            cin >> a >>b >>c;
            g[a][b] = min(g[a][b], c);
        }
        int t = djst();
        
        cout << t;
        
        return 0;
    }
    /*
    0x3f3f3f3f 代表 正无穷。
    */
    

    优化Dijkstra :

    题目链接
    优先队列的函数补充:
    优先队列数据结构(堆)的函数用法 20.10.17

    可以更新的地方:
    分析:
    
    
    *2、 for(1 ~ n);·;
    *3	找到 不在s中的,距离最近的点 t;——————*2、*3共循环 n^2 次来找点 t;(用小根堆堆来做可时间O(n))
    	,也就是用优先队列,优化后为O(log n)
    
    	就是这里可以优化
     for(int j = 1; j <= n; j ++)					/* *3 */
                if(!s[j] && (t == -1 || djs[t] > djs[j]))	/* *3 */ 
                    t = j;			
    
    *4	将t加入s;																		——————————————————这里是n次
    *5	用t更新其它点的距离;						—————————————具体操作时m次,遍历所有的边来更新
    堆优化后 整个计算量最大是 O(m log n)。
    堆的写法:
    手写或用优先队列,两者时间是一个级别的,用优先队列,不需要手写堆。
    
    #include<bits/stdc++.h>
    using namespace std;
    const int N = 150010;
    
    int n, m;
    int djs[N];
    bool st[N];
    int ne[N], e[N], h[N], w[N], idx = 0;
    
    typedef pair<int ,int> P;//距离1的距离,以及点号, 这里默认是按照第一个元素来排序的
    
    void add(int a, int b, int c){
        e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++;
    }
    
    int djst(){
        memset(djs, 0x3f, sizeof djs);
        djs[1] = 0;
        
        priority_queue< P, vector<P>, greater<P> > heap;/* *1 */
        heap.push( {0, 1} );
        
        while(heap.size()){
            auto t = heap.top();
            heap.pop();
            
            int ver = t.second, distance = t.first;
            if(st[ver]) continue;
            
            st[ver] = 1;								/* *2 */
            
            for(int i = h[ver]; i != -1; i = ne[i]){
                int j = e[i];
                if(djs[j] > distance + w[i]){
                    djs[j] = distance + w[i];
                    heap.push({djs[j], j});
                }
            }
        }       
       
        if(djs[n] == 0x3f3f3f3f) return -1;
        return djs[n];
    }
    
    int main(){
        cin >> n >> m;
        memset(h, -1, sizeof h);
        while(m --){
            int a, b, c;
            cin >> a >>b >>c;
            add(a, b, c);
        }
        cout << djst() << endl;
        return 0;
    }
    

    给定一个n个点m条边的有向图,图中可能存在重边和自环,所有边权均为非负值。

    请你求出1号点到n号点的最短距离,如果无法从1号点走到n号点,则输出-1。

    输入格式
    第一行包含整数n和m。

    接下来m行每行包含三个整数x,y,z,表示存在一条从点x到点y的有向边,边长为z。

    输出格式
    输出一个整数,表示1号点到n号点的最短距离。

    如果路径不存在,则输出-1。

    数据范围
    1≤n,m≤1.5×105,
    图中涉及边长均不小于0,且不超过10000。

    输入样例:
    3 3
    1 2 2
    2 3 1
    1 3 4
    输出样例:
    3
    *1 强调:“>”不要两个拼在一起。
    less是从大到小,greater是从小到大。
    第一个参数为数据类型。
    第二个参数为容器类型。
    第三个参数为比较函数。
    *2 千万不要忘记。

  • 相关阅读:
    NOIP2018 游记
    HDU1556 敌兵布阵
    BZOJ 1032 [JSOI2007]祖码Zuma
    BZOJ 1068 [SCOI2007]压缩
    BZOJ 1090 [SCOI2003]字符串折叠
    BZOJ 1260 [CQOI2007]涂色paint
    BZOJ 1055 [HAOI2008]玩具取名
    HDU 5151 Sit sit sit
    HDU 4283 You Are the One
    vue系列8:webpack
  • 原文地址:https://www.cnblogs.com/yuanyulin/p/14026759.html
Copyright © 2011-2022 走看看