最短路径问题
1. 概述
1. 抽象
在网络(带权图)中,求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径
- 这条路径就是两点之间的最短路径(ShorttestPath)
- 第一个顶点为源点(Source)
- 最后一个顶点为终点(Destination)
2. 分类
- 单源最短路径问题:从某固定源点出发,求其到所有其他顶点的最短路径
- (有向)无权图
- (有向)有权图
- 多源最短路径问题:求任意两顶点间的最短路径
2. 无权图的单源最短路算法
按照递增(非递减)的顺序找出到各个顶点的最短路
void Unweighted( Vertex s){
queue<Vertex> q;
q.push(s);
wile(!q.empty()){
v = q.front(); q.pop();
for( V 的每个临界点 W){
dist[W] = dist[v] + 1; // 当前距离上一距离 + 1
path[W] = v; // s 到 w 的必经顶点就是前一个顶点 v
q.push(W);
}
}
}
3. 有权图的单源最短路算法
Dijkstra 算法
- 令 S = {源点s + 已经确定了最短路径的顶点 vi_ii}
- 对任一未收录的顶点 v,定义 dist[v] 为 s 到 v 的最短路径长度,但该路径仅经过 S 中的顶点。即路径 {s→(vi_ii∈S)→v} 的最小长度
- 若路径是按照递增(非递减)的顺序生成的,则
- 真正的最短路必须只经过 S 中的顶点
- 每次从未收录的顶点中选一个 dist 最小的收录
- 增加一个 v 进入 S,可能影响另外一个 w 的 dist 值
- dist[w] = min{dist[w],dist[v] + <v,w>的权重}
void Dijkstra( Vertex s ){
while(1){
V = 未收录顶点中dist最小值;
if( 这样的V不存在 )
break;
collected[V] = true;
for( V 的每个邻接点 W )
if( collected[W] == false )
if(dist[V] + E<V,W> < dist[W]){
dist[W] = dist[V] + E<V,W>;
path[W] = V;
}
}
}
取出未收录顶点中dist最小值 和 更新dist[W]的操作可以考虑两种方法:
-
直接扫描所有未收录顶点 ——O(|V|)
T = O(|V|2^22 + |E|) ——稠密图效果更好
-
将dist存在最小堆中 ——O(log|V|)
更新dist[w]的值 —O(log|V|)
T = O(|E|log|V|) —— 稀疏图效果更好
#include<iostream>
#include<stdlib.h>
#define Inf 1000000
#define Init -1
#define MaxVertex 100
typedef int Vertex;
int G[MaxVertex][MaxVertex];
int dist[MaxVertex]; // 距离
int path[MaxVertex]; // 路径
int collected[MaxVertex]; // 被收录集合
int Nv; // 顶点
int Ne; // 边
using namespace std;
// 初始化图信息
void build(){
Vertex v1,v2;
int w;
cin>>Nv

最低0.47元/天 解锁文章
6266





