单源出发,最短路径,松弛。
Dijkstra 算法是所有最短路径算法中某种意义上最快的,只是代码略为难写。
松弛
Dijkstra 算法的精髓,就是两个字:松弛。包括所有的最短路径算法,都依靠的是这个词。
何为松弛?假设现有若干个点,点 \(v\) 到起点的最短路径很大,但是有另一个点 \(u\),它的路径值较小,而且它与 \(v\) 相连,则可以用 \(u\) 点的路径值加上边权值得出更优的 \(v\) 的路径值,即 \(dis_v=min(dis_v,dis_u+w)\)。
类似于 BFS 的代码结构
Dijkstra 类似一个 BFS,每次从一个顶点(已经被更新过的)更新所有它能更新的结点。而选出的这个结点就是已经更新过的结点中路径值的最小值。
不要忘记判断是否重复利用某个点。
我们可以采用优先队列(堆)来实现这个最小值的需求。
初始化
每个点的最初路径值都是 \(\infty\),只有起始结点的值为 \(0\),很好理解。
代码
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;
typedef long long ll;
const ll MAXN = 200005;
const ll INF = 2147483647;
struct Edge{
ll v, w;
};
vector<Edge> adj[MAXN];
struct Que{
ll d, v;
bool operator <(const Que &o)const{
return v > o.v;
}
};
ll n, m, dis[MAXN], vis[MAXN];
priority_queue<Que> q;
void Dijkstra(ll s){
for(ll i = 1; i <= n; i ++){
dis[i] = INF;
vis[i] = 0;
}
dis[s] = 0;
q.push({s, 0});
while(!q.empty()){
ll u = q.top().d;
q.pop();
if(vis[u])continue;
vis[u] = 1;
for(auto it : adj[u]){
ll v = it.v, w = it.w;
if(dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
q.push({v, dis[v]});
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
ll s;
cin >> n >> m >> s;
for(ll i = 1; i <= m; i ++){
int u, v, w;
cin >> u >> v >> w;
adj[u].push_back({v, w});
}
Dijkstra(s);
for(ll i = 1; i <= n; i ++){
cout << dis[i] << " ";
}
return 0;
}
标签:图论,ll,路径,单源,Dijkstra,MAXN,include,dis
From: https://www.cnblogs.com/Allen-yang2010/p/18591529