zoukankan      html  css  js  c++  java
  • 三个最短路算法

    最短路径算法

    Floyed-Warshall O(N3)

    算法描述:
        a.初始化:如果点u,和v有相连的边则第dis[u][v] = dis[v][u] = distance;
        如果不相连则等于无穷大。
        
        b.核心代码 (实用于负的权值)
            ```
    
      1         for (int k = 1; k <= n; ++ k)
      2             for (int i = 1; i <= n; ++ i)
      3                 for (int j = 1; j <= n; ++ j)
      4                     if (dis[i][j] > dis[i][k] + dis[k][j])
      5                         dis[i][j] = dis[i][k] + dis[k][j];
    ``` c.算法思想分析 三层循环,第一层循环中点k, 第二层,第三层循环起点和终点; 如果点i到点看的距离加上点k到点j的距离小于原先得的距离,这跟新最短距离。

    Dijkstra O(N2)

    是一种从一个点计算到所有点的最短距离的一种算法。
    直接附上代码理解;

    题目 D : 旅游规划 时间限制:1 sec 内存限制:128 MB 提交:6 正确:2

    题目描述 有了一张自驾旅游路线图,你会知道城市间的高速公路长度、以及该公路要收取的过路费。现在需要你写一个程序,帮助前来咨询的游客找一条出发地和目的地之间的最短路径。如果有若干条路径都是最短的,那么需要输出最便宜的一条路径。

    输入 输入说明:输入数据的第1行给出4个正整数N、M、S、D,其中N(2≤N≤500)是城市的个数,顺便假设城市的编号为0~(N?1);M是高速公路的条数;S是出发地的城市编号;D是目的地的城市编号。随后的M行中,每行给出一条高速公路的信息,分别是:城市1、城市2、高速公路长度、收费额,中间用空格分开,数字均为整数且不超过500。输入保证解的存在。

    输出 在一行里输出路径的长度和收费总额,数字间以空格分隔,输出结尾不能有多余空格。

    样例输入

    4 5 0 3 0 1 1 20 1 3 2 30 0 3 4 10 0 2 2 20 2 3 1 20

    样例输出

    3 40

      1 #include <cstring>
      2 #include <algorithm>
      3 #define INF 0x3f3f3f3f
      4 using namespace std;
      5 
      6 constexpr size_t maxn = 505;
      7 
      8 int dt[maxn][maxn];
      9 int dis[maxn];
     10 int cost[maxn];
     11 int dcost[maxn][maxn];
     12 bool vis[maxn];
     13 
     14 int main()
     15 {
     16  int n, m, s, d;
     17  cin >> n >> m >> s >> d;
     18 
     19  for (int i = 0; i < n; ++ i)
     20      for (int j = 0; j < n; ++ j)
     21          dt[i][j] = dcost[i][j] = INF;
     22 
     23  for (int i = 0; i < m; ++ i)
     24  {
     25      int a, b, c, d;
     26      cin >> a >> b >> c >> d;
     27      dt[a][b] = dt[b][a] = c;
     28      dcost[a][b] = dcost[b][a] = d;
     29  }
     30 
     31  for (int i = 0; i < n; ++ i)
     32  {
     33      dis[i] = dt[i][s];
     34      cost[i] = dcost[i][s];
     35  }
     36  dis[s] = 0; vis[s] = true;
     37  int Md, v0;
     38  v0 = s;
     39  //Dijkstra O(N2)
     40  for (int i = 0; i < n; ++ i)
     41  {
     42      Md = INF;
     43      for (int j = 0; j < n; ++ j)
     44      {
     45          if (!vis[j])
     46              if(dis[j] < Md)
     47              {
     48                  Md = dis[j];
     49                  v0 = j;
     50              }
     51      }
     52 
     53  vis[v0] = true;
     54 
     55  for (int i = 0; i < n; ++ i)
     56  {
     57      if (!vis[i] && Md + dt[v0][i] < dis[i]){
     58          dis[i] = Md + dt[v0][i];
     59          cost[i] = cost[v0] + dcost[v0][i];
     60      }
     61      else if (!vis[i] && Md + dt[v0][i] == dis[i] && cost[i] > dcost[v0][i] + cost[v0]){
     62          cost[i] = cost[v0] + dcost[v0][i];
     63      }
     64  }
     65 }
     66  cout << dis[d] << " " << cost[d] << endl;
     67  return 0;
     68 }
     69 
    起点为s,dis[v]表示s->v的最短距离,pre[v]为v的前驱,可以用来输出路径。

    Bellman-Ford O(NE)(只能处理存在负权的最短路径问题不,无法解决负权回路问题)

    是用来计算从一个点到其它点的最短距离的算法,和Dijkstra一样是以种单元最短路径算法。
    
    时间复杂度:O(NE)N是顶点数,E是变得数。
    算法实现:
        设s为起点,dis[v]是s到v的最短距离,pre[v]是v的前驱,w[j] 是边j的长度,且j连接u,v。
    初始化;dis[s] = 0, dis[v] = 无穷, pre[s] = 0;
    核心代码:
    ```
    
      1     for (i = 1; i <= n - 1; ++ i)
      2         for (j = 1; j <= E; ++ j) //要枚举所有的边,不是点。
      3             if(dis[u] + w[j] < dis[v]) // u, v 是这条边连接的两个点。
      4             {
      5                 dis[v] = dis[u] + w[j];
      6                 pre[v] = u;
      7             }
    ``` 算法分析&思路: 一开始认为起点是白点(dis[1] = 0),每一次都枚举所有的边,必然会有一些边,连接着白点和蓝点, 因此,每次都能用所有的白点去修改所有的蓝点。每一次循环至少有以个蓝点变成白点.
    追求吾之所爱
  • 相关阅读:
    桥牌笔记:双挤
    打造GTD style的办公环境 V1.0
    《Two Dozen Short Lessons in Haskell》学习(四)
    跑步机到了,看能坚持多久
    《Two Dozen Short Lessons in Haskell》学习(十) Private Definitions — the whereclause
    赶在世界末日前完成的2012年全年总结
    《Two Dozen Short Lessons in Haskell》学习(三)
    《Two Dozen Short Lessons in Haskell》学习(六)
    《Two Dozen Short Lessons in Haskell》学习(二)
    桥牌笔记:进手张
  • 原文地址:https://www.cnblogs.com/rstz/p/14391082.html
Copyright © 2011-2022 走看看