最短路板子
spfa
#include <bits/stdc++.h>
using namespace std;
int dis[500010], n, m, x, y, w, t = 1, s, h, head[500010], tot;
bool v[100010];
queue<int> q;//手写队列:int q[200000];
/*
head[i]表示到达i点的最后一条边的编号;
dis[i]表示从起点到i点目前为止的最短距离;
vis[i] = 1;表示点i在队列里;
vis[i] = 0;表示点i不在队列里;
数组q是手写队列;
h是队头,t是队尾。
*/
struct node
{
int to;//这条边的终点;
int len;//这条边的长度;
int from;//前一条边;
}e[500010];
void add(int from/*起点*/,int to/*终点*/,int w/*权值*/)
{
e[++ tot].to = to;//更新当前这条边的终点;
e[tot].len = w;//更新当前这条边的长度;
e[tot].from = head[from];//e[tot].from表示当前读入的这条边的上一条边;head[from]表示到当前读入的边为止(不包括这条边)的上一条边的序号;
head[from] = tot;//更新为 当前读入的边为止(包括这条边)的上一条边的序号;
}
void SPFA()
{
while(! q.empty())
{//队列不为空。手写队列:while(h <= t)
int u = q.front();//取出队首。手写队列:h ++; int u = q[h];
q.pop();//队首出队。
v[u] = 0;
for(int i = head[u]; i; i = e[i].from)
{//head[u]是指可以到达点u的上一条边,如果存在head[u](也就是head[u]不为0,因为0是初始值),说明有一条边可以到达点u。所以i变成head[u]。e[i].from是指可以到达head[u]这条边的起点的边的编号。
int h = e[i].to;
if(dis[h] > dis[u] + e[i].len)
{//如果从起点到v的距离大于从起点到点i,再从点i到点u,再从点u到点v的距离,更新从起点到点v的最短路;
dis[h] = dis[u] + e[i].len;
if(v[h] == 0)
{//没有入过队就入队;
v[h] = 1;//标志改为1,表示已经入队;
q.push(h);//手写队列:t++; q[t]=h;
}
}
}
}
}
int main(){
cin >> n >> m >> s;
for(int i = 1; i <= m; i ++)
{
cin >> x >> y >> w;//输入这条边的起点f,终点g和长度w;
add(x, y, w);//建图;
}
for(int i = 1; i <= n; i ++)
{
dis[i] = 2147483647;
}
dis[s] = 0;
q.push(s);//起点入队。手写队列:q[t] = s;
v[s] = 1;//表示起点已入队;
SPFA();
for(int i = 1; i <= n; i ++)
{
cout << dis[i] << ' ';
}
return 0;
}
Dijkstra
*全译文版Dijkstra堆优化。*/
#include <bits/stdc++.h>
using namespace std;
#define itn int
#define fro for
const int _ = 100086;
const int __ = 2147483647;
int n, m, v[_], head[_], dis[_], x, y, w, t, s;
priority_queue<pair<int, int>, vector<pair<int, int> >, greater<pair<int, int> > > q;//小根堆。
struct hhh
{//高兴。
int len, to, nxt;
}e[500050];
void add(int a, int b, int c)
{//链式前向星(从a走到b距离是c)
e[++ t].len = c;//表示这条边的长度;“t”表示这是第几条边(编号)。
e[t].to = b;//表示这条边的终点。
e[t].nxt = head[a];//表示当前的边的上一条边;head[a]表示当前的边的上一条边的上一条边的编号;
head[a] = t;//t”是当前的边的上一条边的编号。
}
void dijkstra(int x)
{//Dijkstra堆优化。
q.push(make_pair(0, x));//源点的距离和它自己入堆。
for(int i = 1; i <= n; i ++)
{
dis[i] = __;//初始化。
}
dis[x] = 0;//自己到自己的距离是0。
while(! q.empty())
{//堆不为空,就说明不是所有与源点联通的点都被遍历到了,就要一直找。
int now = q.top().second;//取出堆顶的点。
q.pop();//把堆顶扔进垃圾桶里。
if(v[now])
{//被用过就跳楼。
continue;
}
v[now] = 1;//标记。
for(int i = head[now]; i; i = e[i].nxt)
{//遍历所有与now这个点直接相邻的点。
if(dis[e[i].to] > dis[now] + e[i].len)
{
dis[e[i].to] = dis[now] + e[i].len;//更新到该点的最短路。
q.push(make_pair(dis[e[i].to], e[i].to));//将新鲜更新完的点扔进堆里。
}
}
}
}
int main()
{
cin >> n >> m >> s;
for(int i = 1; i <= m; i ++)
{
cin >> x >> y >> w;
add(x, y, w);
}
dijkstra(s);
for(int i = 1; i <= n; i ++)
{
cout << dis[i] << ' ';
}
return 0;
}
感谢肝·神祇变量·OIer·硬化·悲伤蛙一世
de全译注释
以下是签名
${\scr {jade }}$ ${\scr {seek }}$
本文来自博客园,作者:BIxuan—玉寻,转载请注明原文链接:https://www.cnblogs.com/zhangyuxun100219/p/18871806

浙公网安备 33010602011771号