Luogu P4779 【模板】单源最短路径(标准版)(Dijkstra+堆优化模板)

qwq

dij其实和prim挺像的,prim是找权值最小点,dij是找边,

用一个优先队列就可以在加入边的时候直接排序,避免了每次遍历更新min

 priority_queue <pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;

这句话就能把大根堆转化为小根堆(pair中的第一个值first最小的在最上面),

同时pair<边权,序号>便于在对边权排序的同时调用这条边的序号。

注意事项:

  1. 找点的时候要有一个vis标记是否访问过(剪枝)
  2. 加边的时候要注意是有向图还是无向图...

代码如下

#include<cstdio>
#include<iostream>
#include<queue>
using namespace std;

const int maxn = 500005;
const int INF = 2147483647;
int n,m,s,x,y,z,cnt;
int to[maxn],next[maxn],head[maxn],val[maxn],dis[maxn];
bool vis[maxn];

void add(int x,int y,int z) {
    to[++cnt] = y;
    next[cnt] = head[x];
    head[x] = cnt;
    val[cnt] = z;
}

void dijkstra(int s) {
    priority_queue <pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
    dis[s] = 0;
    q.push(make_pair(0,s));
    while(!q.empty()) {
        int u = q.top().second;
        q.pop();
        if(vis[u])continue;
        vis[u] = 1;
        for(int i = head[u]; i; i = next[i]) {
            int v = to[i];
            if(dis[v] <= dis[u] + val[i]) continue;
            dis[v] = dis[u] + val[i];
            q.push(make_pair(dis[v],v));
        }
    }
    return;
}

int main() {
    scanf("%d%d%d",&n,&m,&s);
    for(int i = 1; i <= m; i++) {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    for(int i = 1; i <= n; i++)
        dis[i] = INF;
    dijkstra(s);
    for(int i = 1; i <= n; i++)
        cout << dis[i] << ' ';
    return 0;
}

 

原文地址:https://www.cnblogs.com/mogeko/p/10046758.html