Luogu P4779 【模板】单源最短路径(标准版)(Dijkstra+堆优化模板)
dij其实和prim挺像的,prim是找权值最小点,dij是找边,
用一个优先队列就可以在加入边的时候直接排序,避免了每次遍历更新min
priority_queue <pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
这句话就能把大根堆转化为小根堆(pair中的第一个值first最小的在最上面),
同时pair<边权,序号>便于在对边权排序的同时调用这条边的序号。
注意事项:
- 找点的时候要有一个vis标记是否访问过(剪枝)
- 加边的时候要注意是有向图还是无向图...
代码如下
#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; }