dijkstra主要方法:
- 分成两组:已经确定最短路、尚未确定最短路
- 从第2组中选择路径长度最短的点放入第1组并扩展
- 本质是贪心,只能应用于正权图
- 普通的Djkstra算法O(N^2)
- 堆优化的Dijkstra算法O(NlogN)-O(MlogN)
引入概念——松弛操作:
- 原来用一根橡皮筋直接连接a、b两点,现在有一点k,使得a − > k − > b比a − > b的距离更短,则把橡皮筋改为a − > k − > b,这样橡皮筋更加松弛。
- 代码实现:
if(dis[b]>dis[k]+w[k][b]) dis[b]=dis[k]+w[k][b];
算法描述:
设起点为s,dis[v]表示从指定起点s到v的最短路径pre[v]为v的前驱,用来输出路径
1.初始化
memset(dis,+∞)
memset(vis,false);
(int v = 1 ; v <= n ; v ++ )
dis[v]=w[s][v];
dis[s]=0; pre[s]=0; vis[s]=true;
2. 松弛n−1次
(1)在没有被访问过的点中找一个相邻顶点k,使得dis[k]是最小的;
(2)k标记为已确定的最短路vis[k]=true;
(3)用for循环更新与k相连的每个未确定最短路径的顶点v(所有未确定最短路的点都松弛更新)
3.算法结束
dis[v]为s到v的最短路距离;pre[v]为v的前驱结点,用来输出路径
代码演示
以下为优化后的代码
struct edge{
int to , nxt , w;
}a[MAXN];
void add(int u , int v , int w) {
a[++ cnt].w = w;
a[cnt].to = v;
a[cnt].nxt = head[u];
head[u] = cnt;
}
struct node{
int id , w;
node(int iid , int ww) {
id = iid;
w = ww;
}
friend bool operator<(node x , node y) {
return x.w > y.w;
}
};
priority_queue<node> q;
void dijkstra() {
memset(dis , 0x3f , sizeof(dis));
dis[s] = 0;
q.push(node(s , 0));
while(!q.empty()) {
int u = q.top().id;
q.pop();
if (vis[u]) continue;
vis[u] = 1;
for (int i = head[u] ; i ; i = a[i].nxt) {
int v = a[i].to , w = a[i].w;
if (dis[v] > dis[u] + w) {
dis[v] = dis[u] + w;
q.push(node(v , dis[v]));
}
}
}
}