但是,我们会发现刚刚讲的朴素Dijkstra算法(高情商:朴素 ; 低情商: 低效)的套路不适用于稀疏图,很容易会爆时间;
所以,我们要对其中的一些操作进行优化,首先我们发现找到里起始点最近的点去更新其他的点的时候是O(n)的,又因为是稀疏图我们不能用邻接矩阵来存储,所以我们就会想到用邻接表来存储,那么我们在找能更新的位置时,我们就会根据邻接表的单链表进行存储,把更新后的点放入堆中,这样的时间复杂度是O(mlogn)的;
然后最复杂的地方是,我们再用朴素的 Dijkstra算法查找到起始点的最近距离的时候我们用了O(n^2)的时间复杂度,我们要把这里给优化是效果最好的,所以我们引入了堆(近似完全二叉树 || 优先队列:聪明的人都知道用STL,谁还笨笨的手写堆啊!!!),我们从起始点开始push进堆中,然后每个更新的点我们也都放入堆中,因为这个堆能自动的维护大小顺序,我们一开始先定义为一个小根堆,然后每次取堆顶并出堆,就完成了找到里起始点最近的点的目的;
同样的,对于每个节点我们都要用一个st数组来标记,因为我们既然访问到他了,那么他一定是当前离起始点最近的点,我们就可以大胆的将其设为true(st值)!
代码:
#include<bits/stdc++.h>
#define x first
#define y second
#define maxn 150010
using namespace std;
typedef pair<int, int> PII;
int h[maxn],e[maxn],w[maxn],ne[maxn],idx,n,m,dist[maxn];
bool st[maxn];
void add(int a, int b, int c)
{
    e[idx] = b; w[idx] = c; ne[idx] = h[a] ; h[a] = idx++;
}
int dijkstra(){
    memset(dist , 0x3f,sizeof(dist));
    priority_queue<PII , vector<PII> , greater<PII> > heap;
    PII start;
    start.x = 0 ; start.y = 1;
    heap.push(start);
    while(heap.size()){
        PII t = heap.top();
        heap.pop();
        int ver = t.y , distance = t.x;
        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];
                PII mid;
                mid.x = dist[j] ;mid.y = j;
                heap.push(mid);
            }
            
        }
    }
    if(dist[n] == 0x3f3f3f3f) return -1;
    else return dist[n];
}
int main()
{
    memset(h,-1,sizeof(h));
    cin >> n >> m;
    for(int i = 1;i<=m;i++){
        int a,b,c;
        cin >> a >> b >> c;
        add(a, b, c);
    }
    int ans = dijkstra();
    cout << ans;
    return 0;
}
                    
                
                
            
        
浙公网安备 33010602011771号