最短路算法学习笔记
Dijkstra
Dijkstra 是基于贪心的一种算法,适用于非负权的图,求解单源最短路。
算法是这样的:
找出全局距离最小的点 u,并用这个点去更新连接它的 v 点的距离。
时间复杂度 O(n^2),使用堆优化可以优化到 O(m log m)
code
struct node{
int x;
LL y;
bool operator < (const node& no) const{
return no.y < y;
}
};
priority_queue <node> q;
void dij(int u){
memset(dis,0x7f,sizeof(dis));
memset(vis,0,sizeof(vis));
dis[u] = 0;
q.push(node{u,0});
while(!q.empty()){
node tmp = q.top();
q.pop();
int x = tmp.x;
if(vis[x]) continue;
vis[x] = 1;
for(int i = head[x];i;i = e[i].next){
int y = e[i].to,z = e[i].val;
if(dis[y] > dis[x] + z){
dis[y] = dis[x] + z;
q.push(node{y,dis[y]});
}
}
}
}
Bellman_Ford
是一种可以处理负权的单源最短路算法。
算法是这样的:
枚举每条边,并更新这条边上点,称为一次松弛。
重复上诉操作直到没有点被更新。
如果经过了 n 轮松弛后还存在有点被更新,则原图存在负环。
时间复杂度 O(nm).
SPFA
SPFA 是 Bellman_Ford 的队列优化。
松弛节点 x 时找到接下来有可能松弛的点,
即与 x 相邻且最短路被更新的点压入队列。
判断负环只需要是否存在点判断进入队列是否超过 n−1 次。
若有,则有负环。
在一般图上效率很高,但是会被构造数据卡成 O(nm).
code
void spfa() {
memset(dis,0x7f,sizeof(dis));
q.push(s),dis[s] = 0;
while(!q.empty()){
int x = q.front();
q.pop();
vis[x]=0;
for(int i = head[x];i;i = e[i].next) {
int y = e[i].to,z = e[i].val;
if(dis[y] > dis[x] + z) {
dis[y] = dis[x] + z;
if(++cnt[y] >= n) return 0;
if(!vis[y]) Q.push(y),vis[y] = 1;
}
}
}
}

浙公网安备 33010602011771号