原理解释
Dijkstra算法是通过贪心+BFS+动态规划实现的,可以用来计算单个点(源点)到其余任一点的距离大小。
Dijkstra算法的实现分为以下几步:
- 
定义并初始化数组dis[N],其中 disi 表示源点当前距离 i 点的最短距离,再定义一个 bool 数组 vis[N], visi 代表第 i 个点是否被拓展过(即是否达到了最优解)。
 
- 
从未被拓展的点中找出一个离源点最近的点 x(此时它已经是最优解),通过这个点依次松弛和它联通的每一个点距离源点的距离,同时将所松弛的点加入到队列当中。
 
- 
等到队列中没有元素存在之后,结束函数,此时 dis[N] 中的每个点 disi 即代表着距离源点的最小距离。
 
代码实现
朴素法
1 2 3
   | struct Edge { int x, w; };  vector<Edge> g[N];  int dist[N]; 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
   | void dijkstra(int st) {     memset(dist, 0x3f, sizeof dist);     dist[st] = 0;     bitset<N> vis; 
      for (int i = 1; i <= n; i++)     {         int t = -1;         for (int j = 1; j <= n; j++)             if (t == -1 || (!vis[j] && dist[j] < dist[t]))                 t = j; 
          vis[t] = true;                   for (auto &y : g[t])             if (!vis[y.x] && d[y.x] > d[t] + y.w)                 d[y.x] = d[t] + y.w;     } }
   | 
 
队列 / 堆优化
vector 存图
1 2 3 4 5 6 7
   | struct Edge {     int x, w;      bool operator < (const Edge &u) const { return w > u.w; } }; vector<Edge> g[N]; int dist[N];
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | void dijkstra(int st) {     memset(dist, 0x3f, sizeof dist);     dist[st] = 0;     bitset<N> vis;      priority_queue<Edge> heap;     heap.push({st, dist[st]}); 
      while (heap.size())     {         int t = heap.top().x;         heap.pop();
          if (vis[t]) continue;         vis[t] = true;
          for (auto &y : g[t])         {             if (!vis[y.x] && dist[y.x] > dist[t] + y.w)              {                 dist[y.x] = dist[t] + y.w;                  heap.push({y.x, dist[y.x]});              }         }     } }
   | 
 
链式前向星
1 2 3 4 5 6 7 8 9 10
   | struct Edge {     int ver, val;     bool operator < (const Edge &rhs) const { return val > rhs.val; } };
  int n, m, st; int h[N], e[M], ne[M], w[M], idx; int dist[N]; bool vis[N];
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
   | void dijkstra(int st) {     priority_queue<Edge> heap;     memset(dist, 0x3f, sizeof dist), memset(vis, 0, sizeof vis);     dist[st] = 0;     heap.push({st, 0});          while (!heap.empty())     {         auto [ver, val] = heap.top(); heap.pop();                  if (vis[ver]) continue;         vis[ver] = true;                  for (int i = h[ver]; ~i; i = ne[i])         {             int to = e[i];             if (dist[to] > dist[ver] + w[i])             {                 dist[to] = dist[ver] + w[i];                 heap.push({j, dist[j]});             }         }     } }
   |