>Link
ybtoj单源最短路径
luogu P4779
>解题思路
这道题原本以为是SPFA,结果被卡掉了,所以告诉了我求单源最短路径
#无负权边➡一定要用
d
i
j
dij
dij+堆优化(更快)
#有负权边➡一定要用
S
P
F
A
SPFA
SPFA
D
i
j
k
s
t
r
a
Dijkstra
Dijkstra如何实现?
1.将起点到所有点的距离设为
∞
∞
∞,但是起点到自己的距离
d
i
s
s
t
a
r
t
=
0
dis_{start}=0
disstart=0
2.起点已变为白点,剩下的点暂时都为蓝点,
d
i
j
dij
dij的实现就是将所有的点变为白点
3.以当前的白点
s
t
a
r
t
start
start为起始点,枚举与
s
t
a
r
t
start
start相连的每一条边,进行邻点的更新
4.找出
d
i
s
dis
dis最小的蓝点,变其为白点
5.重复循环3、4步骤
堆优化?
我们发现找出
d
i
s
dis
dis最小的蓝点这里很花费时间,所以我们可以建立一个小根堆,用
O
(
l
o
g
n
)
O(logn)
O(logn)的时间快速找出
d
i
s
dis
dis最小的蓝点
注意: D i j k s t r a Dijkstra Dijkstra不能处理负权边!
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define N 200010
using namespace std;
struct edge
{
int to, next, w;
} e[N];
struct node
{
int dis, pos; //距离,位置
bool operator <(const node &x) const
{return x.dis < dis;} //根据dis排的小根堆
//我也不是很懂,kao网上其他大佬的==
};
std::priority_queue<node> q;
int n, m, S, cnt, h[N], c[N];
bool mark[N];
int main()
{
int x, y, w;
scanf ("%d%d%d", &n, &m, &S);
for (int i = 1; i <= m; i++)
{
scanf ("%d%d%d", &x, &y, &w);
e[++cnt] = (edge){y, h[x], w};
h[x] = cnt;
}
memset (c, 0x7f, sizeof (c));
c[S] = 0;
q.push ((node){0, S});
while (!q.empty())
{
node u = q.top();
q.pop();
if (mark[u.pos]) continue;
mark[u.pos] = 1; //mark标记是否以当前点作为白点向周围扩散过
for (int i = h[u.pos]; i; i = e[i].next)
{
int v = e[i].to;
if (c[v] > c[u.pos] + e[i].w)
{
c[v] = c[u.pos] + e[i].w;
if (!mark[v]) q.push((node){c[v], v}); //如果没有扩散过就放进来
}
}
}
for (int i = 1; i <= n; i++)
printf ("%d ", c[i]);
return 0;
}