单源最短路 迪杰斯特拉算法求解&(迪杰斯特拉+优先级队列)

迪杰斯特拉算法思路

单源最短路 迪杰斯特拉算法求解&(迪杰斯特拉+优先级队列)_第1张图片
核心思路
记录能从起点走到的点的最小边权和,然后不断更新直到所有节点遍历完或者不能在遍历新的节点

经典例题:

Single Source Shortest Path I
https://cn.vjudge.net/problem/Aizu-ALDS1_12_B
Single Source Shortest Path
For a given weighted graph G = ( V , E ) G = (V, E) G=(V,E), find the shortest path from a source to each vertex. For each vertex u u u, print the total weight of edges on the shortest path from vertex 0 0 0 to u u u.

Input
In the first line, an integer n n n denoting the number of vertices in G G G is given. In the following n n n lines, adjacency lists for each vertex u u u are respectively given in the following format:

u u u k k k v 1 v_1 v1 c 1 c_1 c1 v 2 v_2 v2 c 2 c_2 c2 v k v_k vk c k c_k ck

Vertices in G G G are named with IDs 0 , 1 , . . . , n − 1 0, 1, ..., n-1 0,1,...,n1. u u u is ID of the target vertex and k k k denotes its degree. v i ( i = 1 , 2 , . . . k ) v_i (i = 1, 2, ... k) vi(i=1,2,...k) denote IDs of vertices adjacent to u u u and c i c_i ci denotes the weight of a directed edge connecting u u u and v i v_i vi (from u u u to v i v_i 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 ≤ 100 1 \leq n \leq 100 1n100
0 ≤ c i ≤ 100 , 000 0 \leq c_i \leq 100,000 0ci100,000
∣ E ∣ ≤ 10 , 000 |E| \leq 10,000 E10,000
All vertices are reachable from vertex 0 0 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 
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 
#include 
#include 
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;
}

你可能感兴趣的:(单源最短路 迪杰斯特拉算法求解&(迪杰斯特拉+优先级队列))