• Dijkstra算法and Floyd算法 HDU 1874 畅通工程续


    Dijkstra算法描述起来比较容易:它是求单源最短路径的,也就是求某一个点到其他各个点的最短路径,大体思想和prim算法差不多,有个数组dis,用来保存源点到其它各个点的距离,刚开始很好办,只需要把邻接矩阵里面它到其它点的距离复制过来就行了。剩下的步骤就是找到一个源点到其他点最小的距离,将它加入到已经确定下来的最短距离中,接着更新其他点到源点的距离,因为确定了一些点的最近距离之后,那么到其它未确定的点的距离可能会变小,所以更新一下。

    理论完了 就要实践:http://acm.hdu.edu.cn/showproblem.php?pid=1874

    AC代码:

     1 #include<iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 const int N = 204;
     6 const int INFINITY = 999999999;
     7 int Map[N][N];
     8 void init(int n)
     9 {
    10     for (int i = 0; i < n; i++)
    11         for (int j = 0; j < n; j++)
    12             Map[i][j] = INFINITY;
    13 }
    14 //v0代表源点,n是总数,dis数组表示到其他点的距离
    15 void dijkstra(int v0, int n, int dis[])
    16 {
    17     //标记是否已经找到最短距离
    18     bool Final[n];
    19     memset(Final, false, sizeof(Final));
    20     for (int i = 0; i < n; i++)
    21         dis[i] = Map[v0][i];
    22     dis[v0] = 0;
    23     //源点已经找到
    24     Final[v0] = true;
    25     int min_dis;
    26     for (int i = 1; i < n; i++)
    27     {
    28         min_dis = INFINITY;//找剩下的所有点中最小的一个
    29         int k = 0;
    30         for (int j = 0; j < n; j++)
    31         {
    32             if (!Final[j] && dis[j] < min_dis)
    33             {
    34                 min_dis = dis[j];
    35                 k = j;
    36             }
    37         }
    38         //如果最小的存在,就将它标记已经找到最短距离
    39         if (min_dis < INFINITY)
    40             Final[k] = true;
    41         else
    42             break;//如果找不到最小的,就是不连通图
    43         for (int j = 0; j < n; j++)//更新其他点到它的距离
    44         {
    45             if (!Final[j] && min_dis + Map[k][j] < dis[j])
    46             {
    47                 dis[j] = min_dis + Map[k][j];
    48             }
    49         }
    50     }
    51 }
    52 int main()
    53 {
    54     int n, m;
    55     while (~scanf("%d %d", &n, &m))
    56     {
    57         init(n);
    58         int a, b, x;
    59         for (int i = 0; i < m; i++)
    60         {
    61             scanf("%d %d %d", &a, &b, &x);
    62             //两个城市之间的道路可能有多条,取最小的那条
    63             if (Map[a][b] > x)
    64                 Map[a][b] = Map[b][a] = x;
    65         }
    66         int s, e;
    67         scanf("%d %d", &s, &e);
    68         int ans[n];
    69         dijkstra(s, n, ans);
    70         if (ans[e] < INFINITY)
    71             printf("%d
    ", ans[e]);
    72         else
    73             puts("-1");
    74     }
    75 
    76 
    77     return 0;
    78 }
    View Code

     如果求任意两点之间的最短距离的话,Dijkstra的时间复杂度是O(n^3),用Floyd的话也是O(n^3),但是代码更简洁,更稠密的图实际运行效率更快。它的主要思路就是:因为求任意两点之间的最短距离,那么它得用一个二维数组来实现,其实这个二位数组就可以用邻接矩阵来表示,刚开始是一个点到另外一个点的直接距离,直接距离就是指不经过第三个点可以的距离,算法的整个精髓就是,求点v->w的最短距离,用另外一个点来作为中间点,求v->u>w的距离,如果后者的距离小于前者的距离,就更新v->w的距离。代码一共三层for循环,第一层的意思就是除了这行这列的之外的任意两点之间的距离 通过这个点来作为中间点,一共n个点,所以循环n次,二三两层for循环是从第二个for循环里的点到第三个for循环里的点与通过中间点就行比较。核心代码如下:

    1 void Floyd(int n)
    2 {
    3     for (int i = 0; i < n; i++)
    4         for (int j = 0; j < n; j++)
    5             for (int k = 0; k < n; k++)
    6                 if (Map[j][i] + Map[i][k] < Map[j][k])
    7                     Map[j][k] = Map[j][i] + Map[i][k];
    8 }

    还是这个题,附AC代码:

     1 #include<iostream>
     2 #include <cstdio>
     3 using namespace std;
     4 const int N = 203;
     5 const int INFINITY = 999999999;
     6 int Map[N][N];
     7 void init(int n)
     8 {
     9     for (int i = 0; i < n; i++)
    10         for (int j = 0; j < n; j++)
    11             if (i != j)
    12                 Map[i][j] = INFINITY;
    13 }
    14 void Floyd(int n)
    15 {
    16     for (int i = 0; i < n; i++)
    17         for (int j = 0; j < n; j++)
    18             for (int k = 0; k < n; k++)
    19                 if (Map[j][i] + Map[i][k] < Map[j][k])
    20                     Map[j][k] = Map[j][i] + Map[i][k];
    21 }
    22 int main()
    23 {
    24     int n, m;
    25     while (~scanf("%d %d", &n, &m))
    26     {
    27         init(n);
    28         int a, b, x;
    29         for (int i = 0; i < m; i++)
    30         {
    31             scanf("%d %d %d", &a, &b, &x);
    32             if (Map[a][b] > x)
    33             {
    34                 Map[a][b] = Map[b][a] = x;
    35             }
    36         }
    37         Floyd(n);
    38         int s, e;
    39         scanf("%d %d", &s, &e);
    40         if (Map[s][e] < INFINITY)
    41             printf("%d
    ", Map[s][e]);
    42         else
    43             puts("-1");
    44     }
    45 
    46     return 0;
    47 }
    View Code
  • 相关阅读:
    vue 组件的封装
    原生tab选项卡
    vue 登录验证码
    input type=”file“ change事件只执行一次的问题
    Java容器解析系列(13) WeakHashMap详解
    Java容器解析系列(12) LinkedHashMap 详解
    Java容器解析系列(11) HashMap 详解
    Java泛型之自限定类型
    java Reference
    Thread类源码解析
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4364125.html
Copyright © 2020-2023  润新知