• 关于dijkstra的小根堆优化


    YY引言

    在NOI2018D1T1中出现了一些很震惊的情况,D1T1可以用最短路解决,但是大部分人都在用熟知的SPFA求解最短路。而SPFA的最坏复杂度能够被卡到$O(VE)$。就是边的数量乘以点的数量,而用SPFA的各位都被恶意数据卡成了最坏情况。100->60。这显然很不划算。是时候祭出我们的堆优化$dijkstra$了。

    核心思想

    朴素的dijkstra的核心是一个贪心的过程。每次找当前已知权值的最小的边来进行松弛。但是每次找的过程中都要用$O(m)$的时间。这样很慢。时间复杂度是$O((m+n)n)$。这显然不是我们想要的结果。小根堆的特性是保证堆顶的数是最小的数,所以我们可以用小根堆来替换贪心找最小权值的过程。而使用了小根堆之后的$dijkstra$算法的时间复杂度就变成了$O((m+n)log n)$,而且很稳定。

    代码实现

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    
    using namespace std;
    
    typedef pair<long long, int> P;
    const int maxedge = 2e5+3;
    const int maxnode = 1e5+3;
    priority_queue<P, vector<P>, greater<P> > Q;
    int fir[maxnode], nx[maxedge], u[maxedge], v[maxedge], w[maxedge];
    int dis[maxnode], n, m, s;
    bool book[maxnode];
    inline int read() {
    	int x = 0, f = 1; char c = getchar();
    	while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    	while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
    	return x * f;
    }
    
    int main() {
    	n = read(), m = read(), s = read();
    	memset(fir, -1, sizeof(fir));
    	fill(dis+1, dis+1+n, 2147483647);
    	for(int i=1; i<=m; i++) {
    		u[i] = read(), v[i] = read(), w[i] = read();
    		nx[i] = fir[u[i]];
    		fir[u[i]] = i;
    	}
    	dis[s] = 0;
    	Q.push(P(0, s));
    	while (!Q.empty()) {
    		P x = Q.top();
    		Q.pop();
    		if(x.first > dis[x.second])
    			continue;
    		int k = fir[x.second];
    		while (k != -1) {
    			if(x.first + w[k] < dis[v[k]]) {
    				dis[v[k]] = w[k] + x.first;
    				Q.push(P(dis[v[k]], v[k]));
    			}
    			k = nx[k];
    		}
    	}
    	for(int i=1; i<=n; i++) printf("%d ", dis[i]);
    }
    

      

    模板题目

    Luogu P4779,这个题卡SPFA

    Luogu P3371,这个题不卡SPFA

  • 相关阅读:
    API之绘图(转)
    API之子窗口创建 (转)
    函数调用规范__cdecl和__stdcall的区别一目了然(表格形式)(二)
    _cdecl 和_stdcall及其他调用方式 (一)
    sizeof的深入理解
    VC++中2进制,10进制,16进制相互转换
    传说中的数据结构
    字符串扩展
    数据结构实验之链表七:单链表中重复元素的删除
    数据结构实验之栈一:进制转换
  • 原文地址:https://www.cnblogs.com/bljfy/p/9424496.html
Copyright © 2020-2023  润新知