Dijkstar算法

Dijkstar算法

用途:解决最短路径问题
实现方法:1.普通堆(适合稀疏图,写法简单)2.反向索引堆优化(适合稠密图,有点麻烦)
代码实现:


//普通堆
#include<bits/stdc++.h>
using namespace std;

//比较器,用来构建小根堆
struct cmp{
    bool operator()(pair<int,int>&p1,pair<int,int>&p2){
        return p1.second > p2.second;
    }
};


void solve(){
    int n,m,s;
    cin >> n >> m >> s;
    vector<vector<pair<int,int>>>graph(n+1);
    vector<int>distances(n+1,INT_MAX);
    vector<bool>visited(n+1,false);
    //小根堆
    priority_queue<pair<int,int>,vector<pair<int,int>>,cmp>heap;

    
    for(int i = 0;i<m;i++){
        int u,v,w;
        cin >> u >> v >> w;
        graph[u].push_back({v,w});
    }

    heap.push({s,0});
    distances[s] = 0;

    while(!heap.empty()){
        int u = heap.top().first;
        int w1 = heap.top().second;
        heap.pop();
        if(visited[u]){
            continue;
        }
        visited[u] = true;
        for(auto &e : graph[u]){
            int v = e.first;
            int w2 = e.second;
            if(!visited[v] && distances[v] > w1 + w2){
                distances[v] = w1 + w2;
                heap.push({v,w1+w2});
            }
        }
    }

    for(int i = 1;i<=n;i++){
        cout << distances[i] << " ";
    }
    cout << endl;
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);

    int T = 1;
    //cin >> T;
    while(T--){
      solve();
    }
    return 0;
}

优化版

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl "\n"


//链式前向星+反向索引堆优化
const int MAXN = 100010;
const int MAXM = 200010;


//建图相关
int head[MAXN];
int nxt[MAXM];
int to[MAXM];
int weight[MAXM];
int cnt;

void addEdge(int u,int v,int w){
    nxt[cnt] = head[u];
    head[u] = cnt;
    to[cnt] = v;
    weight[cnt] = w;
    cnt++;
}


//建堆相关
int heap[MAXN];
int distances[MAXN];
int where[MAXN];
int heapsize;

//交换函数
void swap(int i,int j){
    int tmp = heap[i];
    heap[i] = heap[j];
    heap[j] = tmp;

    where[heap[i]] = i;
    where[heap[j]] = j;
}

void build(int n ){
    cnt = 1;
    heapsize = 0;

    fill(head + 1, head + n + 1, 0);
    fill(where+1,where+n+1,-1);
    fill(distances+1,distances+n+1,INT_MAX);
}

void heapInsert(int i){
    while(distances[heap[i]] < distances[heap[(i-1) / 2]]){
        swap(i,(i-1) / 2);
        i = (i-1) / 2;
    }
}

void heapify(int i){
    int l = i*2+1;
    while(l < heapsize){
        int best = l+1 < heapsize && distances[heap[l+1]] < distances[heap[l]] ? l+1 : l;
        best = distances[heap[best]] < distances[heap[i]] ? best : i;
        if(best == i){
            break;
        }
        swap(best,i);
        i = best;
        l = i*2 + 1;
    }
}

bool isEmpty(){
    return heapsize == 0;
}

int pop(){
    int top = heap[0];
    swap(0,--heapsize);
    heapify(0);
    where[top] = -2;    
    return top;
}
void addOrIgnore(int v,int w){
    if(where[v] == -1){
        heap[heapsize] = v;
        distances[v] = w;
        where[v] = heapsize++;
        heapInsert(where[v]);
    }
    else if(where[v] >= 0){
        distances[v] = min(distances[v],w);
        heapInsert(where[v]);
    }
}


void solve(){

    int n,m,s;
    cin >> n >> m >> s;
    build(n);
    distances[s] = 0;

    for(int i = 0;i<m;i++){
        int u,v,w;
        cin >> u >> v >> w;
        addEdge(u,v,w);
    }

    addOrIgnore(s,0);

    while(!isEmpty()){
        int u = pop();
        for(int ne = head[u];ne > 0;ne = nxt[ne]){
            int v = to[ne];
            int w = weight[ne];
            if(distances[v] > w+distances[u]){
                addOrIgnore(v,w+distances[u]);
            }
        }
    }

    for(int i = 1;i<=n;i++){
        cout << distances[i] << " ";
    }
    cout << endl;

}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);


    int T = 1;
    //cin >> T;
    while(T--){
        solve();
    }



    return 0;
}

posted on 2026-05-29 11:04  Sean2299  阅读(13)  评论(0)    收藏  举报

导航