迪杰斯特拉算法思路
核心思路
记录能从起点走到的点的最小边权和,然后不断更新直到所有节点遍历完或者不能在遍历新的节点
经典例题:
Single Source Shortest Path I
https://cn.vjudge.net/problem/Aizu-ALDS1_12_B
Single Source Shortest Path
For a given weighted graph
, find the shortest path from a source to each vertex. For each vertex
, print the total weight of edges on the shortest path from vertex
to
.
Input
In the first line, an integer
denoting the number of vertices in
is given. In the following
lines, adjacency lists for each vertex
are respectively given in the following format:
…
Vertices in are named with IDs . is ID of the target vertex and denotes its degree. denote IDs of vertices adjacent to and denotes the weight of a directed edge connecting and (from to ).
Output
For each vertex, print its ID and the distance separated by a space character in a line respectively. Print in order of vertex IDs.
Constraints
All vertices are reachable from vertex
Sample Input 1
5
0 3 2 3 3 1 1 2
1 2 0 2 3 4
2 3 0 3 3 1 4 1
3 4 2 1 0 1 1 4 4 3
4 2 2 1 3 3
Sample Output 1
0 0
1 2
2 2
3 1
4 3
Reference
Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.
code:
#include <iostream>
using namespace std;
const int MAX=100;
const int INFTY=(1<<21);
const int WHITE=0;
const int GRAY=1;
const int BLACK=2;
int n,m[MAX][MAX];//邻接矩阵 记录从u->v的边权
void dijkstra(){
int minv;
int d[MAX];//用于记录起点s到v的最短路
int color[MAX];//用来记录访问状态 WHITE GRAY BLACK
for(int i=0;i<n;i++){
d[i]=INFTY;
color[i]=WHITE;
}
d[0]=0;
color[0]=GRAY;
while(1){
minv=INFTY;
int u=-1;
for(int i=0;i<n;i++){//在当前节点下寻找边权最小的子节点
if(minv > d[i]&&color[i]!=BLACK){
u=i;
minv=d[i];
}
}
if(u==-1) break;//遍历完整棵树
color[u]=BLACK;//表明u进入目前所生成的最短路,不可修改
for(int v=0;v<n;v++){//存u的最短路
if(color[v]!=BLACK&&m[u][v]!=INFTY)
if(d[v]>d[u]+m[u][v]){
d[v]=d[u]+m[u][v];
color[v]=GRAY;
}
}
}
for(int i=0;i<n;i++){
cout<<i<<" "<<(d[i]==INFTY ? -1 : d[i])<<endl;
}
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
m[i][j]=INFTY;
}
}
int k,c,u,v;
for(int i=0;i<n;i++){
cin>>u>>k;
for(int j=0;j<k;j++){
cin>>v>>c;
m[u][v]=c;
}
}
dijkstra();
}
例题加强版
Single Source Shortest Path II
https://cn.vjudge.net/problem/Aizu-ALDS1_12_C
For a given weighted graph G=(V,E), find the shortest path from a source to each vertex. For each vertex u, print the total weight of edges on the shortest path from vertex 0 to u.
Input
In the first line, an integer n denoting the number of vertices in G is given. In the following n lines, adjacency lists for each vertex u are respectively given in the following format:
u k v1 c1 v2 c2 … vk ck
Vertices in G are named with IDs 0,1,…,n−1. u is ID of the target vertex and k denotes its degree. vi(i=1,2,…k) denote IDs of vertices adjacent to u and ci denotes the weight of a directed edge connecting u and vi (from u to vi).
Output
For each vertex, print its ID and the distance separated by a space character in a line respectively. Print in order of vertex IDs.
Constraints
1≤n≤10,000
0≤ci≤100,000
|E|<500,000
All vertices are reachable from vertex 0
Sample Input 1
5
0 3 2 3 3 1 1 2
1 2 0 2 3 4
2 3 0 3 3 1 4 1
3 4 2 1 0 1 1 4 4 3
4 2 2 1 3 3
Sample Output 1
0 0
1 2
2 2
3 1
4 3
Reference
Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.
code:
#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
const int MAX=10000;
const int INFTY=(1<<21);
const int WHITE=0;
const int GRAY=1;
const int BLACK=2;
int n;
vector< pair<int,int> >adj[MAX];//加权有向图的邻接表表法
void dijkstra(){
priority_queue< pair<int,int> > PQ;//有限队列存存最小节点(默认优先级较大)
int color[MAX],d[MAX];
for(int i=0;i<n;i++){//初始化
d[i]=INFTY;
color[i]=WHITE;
}
d[0]=0;
PQ.push(make_pair(0,0));//起点
color[0]=GRAY;
while(!PQ.empty()){
pair<int,int> f = PQ.top();
PQ.pop();
int u=f.second;
color[u]=BLACK;
//取出最小值,若不是最短路则忽略
if(d[u] < f.first*(-1)) continue;
for(int j=0; j<adj[u].size(); j++){
int v=adj[u][j].first;
if(color[v]==BLACK) continue;
if(d[v]>d[u]+adj[u][j].second){
d[v]=d[u]+adj[u][j].second;
PQ.push(make_pair(d[v]*(-1),v));// priority_queue(默认优先级较大)所以要*-1;
color[v]=GRAY;
}
}
}
for(int i=0;i<n;i++){
cout<<i<<" "<<(d[i]==INFTY ? -1 : d[i])<<endl;
}
}
int main(){
cin>>n;
int k,c,u,v;
for(int i=0;i<n;i++){
cin>>u>>k;
for(int j=0;j<k;j++){
cin>>v>>c;
adj[u].push_back(make_pair(v,c));
}
}
dijkstra();
return 0;
}