配對堆優化Dijkstra算法小記


關於配對堆的一些小姿勢:

1、配對堆是一顆多叉樹。

2、包含優先隊列的所有功能,可用於優化Dijkstra算法。

3、屬於可並堆,因此對於集合合並維護最值的問題很實用。

4、速度快於一般的堆結構(左偏樹,斜堆,隨機堆……),具體時間復雜度:

  • 合並(Merge):$O(1)$;
  • 插入(Insert/Push):$O(1)$;
  • 修改值(Change):$O(1) \sim O(\log n)$;
  • 取出維護的最值(Top):$O(1)$;
  • 彈出堆頂元素(Pop):$O(\log n)$;

 

我們依然拿洛谷的P4779 【模板】單源最短路徑(標准版)來驗證代碼的正確性。

以下是配對堆優化Dijkstra算法的AC代碼:

#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef pair<int,int> pii;
typedef __gnu_pbds::priority_queue<pii,greater<pii>,pairing_heap_tag> Heap;
const int maxn=1e5+10;
const int INF=0x3f3f3f3f;

int n,m,s;
struct Edge{
    int u,v,w;
    Edge(int _u=0,int _v=0,int _w=0){u=_u,v=_v,w=_w;}
};
vector<Edge> E;
vector<int> G[maxn];
void addedge(int u,int v,int w)
{
    E.push_back(Edge(u,v,w));
    G[u].push_back(E.size()-1);
}

int d[maxn];
void dijkstra()
{
    memset(d,0x3f,sizeof(d));

    Heap Q;
    Heap::point_iterator id[maxn];

    d[s]=0;
    id[s]=Q.push(make_pair(d[s],s));
    while(!Q.empty())
    {
        int u=Q.top().second; Q.pop();
        for(int i=0;i<G[u].size();i++)
        {
            Edge &e=E[G[u][i]]; int v=e.v;
            if(d[v]>d[u]+e.w)
            {
                d[v]=d[u]+e.w;
                if(id[v]!=0) Q.modify(id[v],make_pair(d[v],v));
                else id[v]=Q.push(make_pair(d[v],v));
            }
        }
    }
}
int main()
{
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
    }
    dijkstra();
    for(int i=1;i<=n;i++) printf("%d%s",d[i],((i==n)?"\n":" "));
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM