最短路模板(堆优化dijstra + spfa)
作者:互联网
/**\ 最短路模板 输入: n m s t 接下来m行 u, v, w表示u -> v 有一条权值为w的无向边 input: 3 3 1 2 1 2 3 2 3 4 1 3 5 output: 3 \**/ #include <bits/stdc++.h> using namespace std; #define fi first #define se second #define go continue #define int long long #define PII pair<int, int> #define sf(x) scanf("%lld",&x) #define ytz int _; sf(_); while(_--) #define fory(i,a,b) for(int i = a; i <= b; ++i) #define forl(i,a,b) for(int i = a; i >= b; --i) #define debug(a) cout << #a << " = " << a <<endl; const int N = 1e5 + 10; struct node { int to, w, next; } e[N << 1]; int cnt = 0, head[N]; inline void add_edge(int u, int v, int w) { e[++cnt].to = v; e[cnt].w = w; e[cnt].next = head[u]; head[u] = cnt; } inline void init() { cnt = 0; memset(head, -1, sizeof head); } int n, m, s, t; struct v { int x, dis; bool operator < (const v& a) const { return dis > a.dis; //stl默认大顶堆 } }; int dis[N]; bool vis[N]; /**\ dijstra 1、从源点开始每次选取一个离点集距离最近的点t 添加到集合中 2、利用t点对集合中的点进行松弛操作,进行更新 3、使用堆进行1找点的操作降低时间复杂度 4、不能在有负边权的图中使用 \**/ inline void dijstra(int s, int t) { priority_queue<v> q; memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); dis[s] = 0; q.push({s, 0}); while(!q.empty()) { v now = q.top(); q.pop(); if(vis[now.x]) go; vis[now.x] = 1; for(int i = head[now.x] ; i != -1; i = e[i].next) { int y = e[i].to; if(vis[y]) go; if(dis[y] > dis[now.x] + e[i].w) { dis[y] = dis[now.x] + e[i].w; q.push({y, dis[y]}); } } } if(dis[t] > 0x3f3f3f3f) cout << -1; else cout << dis[t]; } /**\ spfa算法思路: 1、每次迭代,取出队头点v,依次枚举从v出发的边,v->u,设边的长度为w 判断dis[v] + w 是否小于dis[u], 小于则更新值, 2、由于s-u的距离变短了,有可能u能改变其他点,使用vis数组判断是否在队列,没有则放入 3、若一个点的入队次数超过n,则存在负环 \**/ queue<int> q1; inline void spfa(int s, int t) { memset(dis, 0x3f, sizeof dis); memset(vis, 0, sizeof vis); dis[s] = 0; vis[s] = 1; q1.push(s); while(!q1.empty()) { int x = q1.front(); q1.pop(); vis[x] = 0; for(int i = head[x]; i != -1; i = e[i].next) { int y = e[i].to; if(dis[y] > dis[x] + e[i].w) { dis[y] = dis[x] + e[i].w; if(!vis[y]) { q1.push(y); vis[y] = 1; } } } } if(dis[t] >= 0x3f3f3f3f) cout << -1; else cout << dis[t]; } inline void solve() { init(); sf(n), sf(m), sf(s), sf(t); fory(i, 1, m) { int x, y, z; sf(x), sf(y), sf(z); add_edge(x, y, z); add_edge(y, x, z); } //dijstra(s, t); spfa(s, t); } signed main() { solve(); return 0; }
标签:q1,now,int,dijstra,vis,spfa,define,模板,dis 来源: https://www.cnblogs.com/-ytz/p/15963572.html