054.Dijkstra模板+反向索引堆优化 + 经典题目

Dijkstra

  • BFS + 贪心(priority_queue)

  • 加权有向图

  • 不能处理负权

Dij(普通堆)

O ( M * logM )

M : 边数

const int N=1e5+5;
const int INF=0x3f3f3f3f;

vector<pair<int,int>>gra[N];
bool vis[N];
int dis[N];

void built(int siz){
    for(int i=1;i<=siz;++i){
        gra[i].clear();
        vis[i]=0;
        dis[i]=INF;
    }
}
void Dijkstra(int s){
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;
    dis[s]=0;
    pq.push({0,s});
    while(pq.size()){
        auto [d,u]=pq.top();
        pq.pop();
        if(vis[u]==0){
            vis[u]=1;
            for(auto [w,v]:gra[u]){
                if(vis[v]==0&&dis[v]>d+w){
                    dis[v]=d+w
                    pq.push({dis[v],v});
                }
            }
        }
    }
}

Dij(反向索引堆)

O ( M * logN )

M : 边数
N : 节点数

const int N=1e5+5;
const int M=2e5+5;
const int INF=0x3f3f3f3f;
int dis[N];


int tot;
int head[N];
int nex[M];
int to[M];
int val[M];

int heap[N];
int tag[N];
int siz;

void built(int n){
    tot=1;
    siz=0;
    for(int i=1;i<=n;++i){
        dis[i]=INF;
        head[i]=0;
        tag[i]=-1;
    }
}
void addEdge(int u,int v,int w){
    nex[tot]=head[u];
    to[tot]=v;
    val[tot]=w;
    head[u]=tot++;
}
void swap(int i,int j){
    int t=heap[i];
    heap[i]=heap[j];
    heap[j]=t;
    tag[heap[i]]=i;
    tag[heap[j]]=j;
}
void up(int i){
    while(dis[heap[(i-1)/2]]>dis[heap[i]]){
        swap(i,(i-1)/2);
        i=(i-1)/2;
    }
}
void down(int i){
    int l=i*2+1;
    while(l<siz){
        int best=l+1<siz&&dis[heap[l+1]]<dis[heap[l]]?l+1:l;
        if(dis[heap[i]]<=dis[heap[best]])return;
        swap(best,i);
        i=best;
        l=2*i+1;
    }
}
int pop(){
    int u=heap[0];
    swap(0,--siz);
    down(0);
    tag[u]=-2;
    return u;
}
void push(int v,int c){
    if(tag[v]==-2)return;
    if(tag[v]==-1){
        heap[siz]=v;
        tag[v]=siz++;
        dis[v]=c;
    }
    else dis[v]=min(dis[v],c);
    up(tag[v]);
}

void Dijkstra(int s){
    push(s,0);
    while(siz){
        int u=pop();
        for(int ei=head[u];ei;ei=nex[ei]){
            push(to[ei],dis[u]+val[ei]);
        }
    }
}

习题

这里我的写法都是普通堆

01 模板

luogu P4779


02 网路延迟时间

leetcode 743

code
class Solution {
    struct e{int to,cost;};
public:
    int networkDelayTime(vector<vector<int>>& times, int n, int k) {
        vector<vector<e>>gra(n+1);
        for(auto edge:times){
            gra[edge[0]].push_back({edge[1],edge[2]});
        }
        auto cmp=[&](e a,e b){return a.cost>b.cost;};
        priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
        vector<int>dis(n+1,0x3f3f3f3f);
        vector<int>vis(n+1,0);
        dis[k]=0;
        pq.push({k,0});
        while(pq.size()){
            auto [cur,d]=pq.top();
            pq.pop();
            if(vis[cur]==0){
                vis[cur]=1;
                for(auto [v,w]:gra[cur]){
                    if(vis[v]==0){
                        int cost=w+d;
                        if(cost<dis[v]){
                            dis[v]=cost;
                            pq.push({v,cost});
                        }
                    }
                }
            }
        }
        int ans=-1;
        for(int i=1;i<=n;++i){
            ans=max(ans,dis[i]);            
        }
        return ans==0x3f3f3f3f?-1:ans;
    }
};

03 最优乘车

luogu P5767

code
const int N=510;
const int INF=0x3f3f3f3f;
int dis[N];
bool vis[N];
vector<pair<int,int>>gra[N];

int Dijkstra(int s,int e,int n){
    for(int i=1;i<=n;++i){
        dis[i]=INF;
        vis[i]=0;
    }
    priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;
    pq.push({0,s});
    dis[s]=0;

    while(pq.size()){
        auto [d,u]=pq.top();
        pq.pop();
        if(vis[u]==0){
            vis[u]=1;
            for(auto [w,v]:gra[u]){
                if(vis[v]==0&&dis[v]>d+w){
                    dis[v]=w+d;
                    pq.push({dis[v],v});
                }
            }
        }
    }
    return dis[e];
}
void solve(){
    int m,n;
    cin>>m>>n;
    cin.ignore();
    cin.ignore();
    for(int i=1;i<=n;++i){
        gra[i].clear();
    }
    for(int i=0;i<m;++i){
        string str;
        getline(cin,str);
        stringstream ss(str);
        vector<int>t;
        int node;
        while(ss>>node){
            t.push_back(node);
        }
        for(int i=0;i<t.size();++i){
            for(int j=i+1;j<t.size();++j){
                gra[t[i]].push_back({1,t[j]});
            }
        }
    }
    int ans=Dijkstra(1,n,n);
    if(ans==INF)cout<<"NO";
    else if(ans==0)cout<<0;
    else cout<<ans-1;
}

04 最小瓶颈

leetcode 1631

code
class Solution {
    struct e{int x,y,d;};
    vector<int>mo{-1,0,1,0,-1};
public:
    int minimumEffortPath(vector<vector<int>>& g) {
        int n=g.size();
        int m=g[0].size();
        vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
        vector<vector<int>>vis(n,vector<int>(m,0));
        auto cmp=[&](e a,e b){return a.d>b.d;};
        priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
        pq.push({0,0,0});
        while(pq.size()){
            auto [x,y,c]=pq.top();
            pq.pop();
            if(vis[x][y]==0){
                if(x==n-1&&y==m-1)return c;
                vis[x][y]=1;
                for(int i=0;i<4;++i){
                    int nx=x+mo[i];
                    int ny=y+mo[i+1];
                    if(nx>=0&&ny>=0&&nx<n&&ny<m&&vis[nx][ny]==0){
                        int nc=max(c,abs(g[x][y]-g[nx][ny]));
                        if(nc<dis[nx][ny]){
                            dis[nx][ny]=nc;
                            pq.push({nx,ny,nc});
                        }
                    }
                }
            }
        }
        return -1;
    }
};

05 水位上升游泳

leetcode 778

code
 class Solution {
    struct e{int x,y,d;};
    vector<int>mo{-1,0,1,0,-1};
public:
    int swimInWater(vector<vector<int>>& g) {
        int n=g.size();
        int m=g[0].size();
        vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
        vector<vector<int>>vis(n,vector<int>(m,0));
        auto cmp=[&](e a,e b){return a.d>b.d;};
        priority_queue<e,vector<e>,decltype(cmp)>pq(cmp);
        pq.push({0,0,g[0][0]});
        while(pq.size()){
            auto [x,y,c]=pq.top();
            pq.pop();
            if(vis[x][y]==0){
                if(x==n-1&&y==m-1)return c;
                vis[x][y]=1;
                for(int i=0;i<4;++i){
                    int nx=x+mo[i];
                    int ny=y+mo[i+1];
                    if(nx>=0&&ny>=0&&nx<n&&ny<m&&vis[nx][ny]==0){
                        int nc=max(c,g[nx][ny]);
                        if(nc<dis[nx][ny]){
                            dis[nx][ny]=nc;
                            pq.push({nx,ny,nc});
                        }
                    }
                }
            }
        }
        return -1;
    }
};

06 概率最大的路径

leetcode 1514

code
class Solution {
    struct st{
        int u;
        double d;
    };
public:
    double maxProbability(int n, vector<vector<int>>& edges, vector<double>& suc, int s, int e) {
        vector<vector<st>>gra(n);
        for(int i=0;i<(int)suc.size();++i){
            gra[edges[i][0]].push_back({edges[i][1],suc[i]});
            gra[edges[i][1]].push_back({edges[i][0],suc[i]});
        }
        vector<double>dis(n,0);
        vector<bool>vis(n,0);
        auto cmp=[](st a,st b){return a.d<b.d;};
        priority_queue<st,vector<st>,decltype(cmp)>pq(cmp);
        pq.push({s,1});
        dis[s]=1;
        while(pq.size()){
            auto [u,d]=pq.top();
            pq.pop();
            if(u==e){
                return d;
            }
            if(vis[u]==0){
                vis[u]=1;
                for(auto [v,w]:gra[u]){
                    double nd=d*w;
                    if(nd>dis[v]){
                        dis[v]=nd;
                        pq.push({v,nd});
                    }
                }
            }
        }
        return 0;
    }
};

07 使网格图至少有一条有效路径的最小代价

leetcode 1368

code
class Solution {
    vector<int>mo{-1,0,1,0,-1};
    struct st{
        int x;
        int y;
        int c;
    };
public:
    int minCost(vector<vector<int>>& g) {
        int n=g.size();
        int m=g[0].size();
        vector<vector<int>>dis(n,vector<int>(m,0x3f3f3f3f));
        vector<vector<bool>>vis(n,vector<bool>(m,0));
        auto cmp=[](st a,st b){return a.c>b.c;};
        priority_queue<st,vector<st>,decltype(cmp)>pq(cmp);
        pq.push({0,0,0});
        dis[0][0]=0;
        while(pq.size()){
            auto [x,y,c]=pq.top();
            pq.pop();
            if(x==n-1&&y==m-1)return c;
            if(vis[x][y]==0){
                vis[x][y]=1;
                int xx=x,yy=y;
                if(g[x][y]==1)yy++;
                if(g[x][y]==2)yy--;
                if(g[x][y]==3)xx++;
                if(g[x][y]==4)xx--;
                for(int i=0;i<4;++i){
                    int nx=x+mo[i];
                    int ny=y+mo[i+1];
                    if(nx<0||ny<0||nx>=n||ny>=m)continue;
                    int nc=c+1;
                    if(xx==nx&&yy==ny)nc--;
                    if(dis[nx][ny]>nc){
                        dis[nx][ny]=nc;
                        pq.push({nx,ny,nc});
                    }
                }
            }
        }
        return -1;
    }
};

posted @ 2026-01-20 23:21  射杀百头  阅读(2)  评论(0)    收藏  举报