Dijkstra堆优化 | priority_queue , vector >, greater<>>

距离PAT秋季考试还有 1 天。
听说邻接表存图➕dijkstra堆优化能时间复杂度降很多,速成一下吧。
原本是因为今年复试上机最后一题Dijkstra+DFS超时,想着学一下堆优化试试,刚刚在群里看到,对每个查询Dijkstra一次,堆优化后最后一个点300ms以内,在查询之前就dijkstra救护中心(最多10次)dist打表,查询的时候仅仅dfs找路径,最后一个case 60ms 内就️。看来还是思路重要啊qaq……但还是学一下堆优化Dijkstra……

Dijkstra堆优化

  • 主要是优化找当前还没确定最短距离的点的那一步。

  • priority_queue , vector >, greater<>> pq;
    pair,dist小的在队列中靠前。
    头文件queue,functional(greater<>)。

  • 优先队列不提供修改队内某元素优先级的的操作,因此在得到某结点x的更小的dist后,更新dist[x],再直接再入队一个pair (new_dist,x) 就好。
    因为new_dist比队列中结点x原先的dist要小,必定比原先那个“过时”的元素先出队。

  • 用done[]布尔数组来确保不重复处理出队的结点。
    若已经处理过结点x,pop掉,continue即可。

实战一下1025 | 已经没什么好害怕了

#include 
#include 
#include 
#include 
#include 

#define LL long long
#define INF 0x3fffffff
using namespace std;
int NN, MM, PP, KK; // 0 - NN  NN+1
LL dist[1000001], rdist[1000001];
vector> graph[1000001], rgraph[1000001];

void Dijkstra(LL dd[], const vector> gg[]) { // src = 0
    bool done[1000001] = {false};
    fill(dd, dd + 1000001, INF);
    priority_queue, vector>, greater>> pq;
    pq.push(make_pair(0, 0)); // dist[src] = 0, src = 0
    while (!pq.empty()) {
        int curr = pq.top().second;
        LL d = pq.top().first;
        pq.pop();
        if (done[curr]) continue;
        done[curr] = true;
        for (auto &item: gg[curr]) {
            if (!done[item.first] && d + item.second < dd[item.first]) {
                dd[item.first] = d + item.second;
                pq.push(make_pair(dd[item.first], item.first));
            }
        }
    }
}

int main() {
    int v1, v2, temp;
    scanf("%d%d%d%d", &NN, &MM, &PP, &KK);
    vector k_targets(KK);
    for (int i = 0; i < PP; i++) {
        scanf("%d", &temp);
        graph[0].emplace_back(temp, 0);
        graph[temp].emplace_back(0, 0);
        rgraph[0].emplace_back(temp, 0);
        rgraph[temp].emplace_back(0, 0);
    }
    for (int i = 0; i < KK; ++i) {
        scanf("%d", &k_targets[i]);
    }
    for (int i = 0; i < MM; i++) {
        scanf("%d%d%d", &v1, &v2, &temp);
        graph[v1].emplace_back(v2, temp);
        rgraph[v2].emplace_back(v1, temp);
    }
    LL res = 0, mmax = -1;
    Dijkstra(dist, graph);
    Dijkstra(rdist, rgraph);
    for (auto &item: k_targets) {
        res += (dist[item] + rdist[item]);
        mmax = max(mmax, rdist[item]);
    }
    printf("%lld\n", res - mmax);
    return 0;
}

你可能感兴趣的:(Dijkstra堆优化 | priority_queue , vector >, greater<>>)