• 最短路径问题【浙大10年机试真题】 Dijkstra算法求单源最短路径


    昨天下午的热身赛D题---《旅游啦》,刚开始以为是要先求单源最短路径,于是呼呼啦啦把DJ的算法搬出来实现,完了后才发现不需要这么做,题目其实是想考察图的最优代价深度优先搜索,无奈最后卡在了回溯时的代价求和。

    那道题以后再去A掉,现在先写这个最短路径,关于图的各种应用算法,考研时也要求掌握,不过离上机实现还差一点,Dj的算法实际就是贪心在图论中的应用,使用final[i]记录编号为i的结点此时是否和源点在同一集合中,使用dist[i]记录从源点到i结点的当前最短路径长度,不过这道题另外增加了路径花费,于是把dist封装成结构体,这无关技术,不必赘述,用pre[i]记录寻找到i结点时的前置结点,可根据该数组顺藤摸瓜,最终构造出整条路径,这道题只要求求dist值,所以pre数组可以省略。

    算法刚开始时,将final[s](s为源点)置为1,其余结点的final值置为0,将dist[i]的值初始化为e[s][i],不相连的话以-1代替,因为不知道OJ上int的最大值,以-1更保险。初始化完成,在dist中寻找满足以下两个条件的结点j:1.final[j] == 0; 2. dist[j]值最小。这个点即为该轮循环找到的最佳跳点,并入集合中,即final[j]置为1,以j结点为跳点,更新dist数组中所有未并入集合中的结点,如果dist[i] > dist[j] + e[j][i](当然前提是j需要与i直接连通), 则将dist[i]更新为dist[j] + e[j][i]。循环上述"跳点--更新dist--更新跳点"的过程,直至需要寻找的终点t并入集合中,算法结束,直接输出dist[t]即可AC。

    以下是代码,内存开大是为了方便操作,用动态分配内存的方法可以压缩掉多余的开销:

      1 #include <stdio.h>
    2 #include <stdlib.h>
    3
    4 typedef struct{
    5 int d;
    6 int p;
    7 }edge;
    8
    9 edge e[1000][1000];
    10 int final[1000];//该点是否和源点属于同一集合
    11 edge dist[1000];//记录从源点到其他个各顶点当前最短路径长度和最小花费
    12
    13 int main()
    14 {
    15 long n,m;
    16 int temp1,temp2,temp3,temp4;
    17 long i,j;
    18 int s,t;
    19 int minlength,minprice,templength,tempprice;
    20 int jump;//跳点
    21 while(scanf("%ld %ld",&n,&m) != EOF && (n != 0 || m != 0))
    22 {
    23 for(i =0; i < n; i ++)
    24 {
    25 for(j = 0; j < n; j ++)
    26 {
    27 e[i][j].d = -1;
    28 e[i][j].p = -1;
    29 }
    30 }
    31 for(i = 0; i < n; i ++)
    32 {
    33 final[i] = 0;
    34 }
    35 for(i = 0; i < m; i ++)
    36 {
    37 scanf("%d %d %d %d",&temp1,&temp2,&temp3,&temp4);
    38 e[temp1 - 1][temp2 - 1].d = temp3;
    39 e[temp1 - 1][temp2 - 1].p = temp4;
    40 e[temp2 - 1][temp1 - 1].d = temp3;
    41 e[temp2 - 1][temp1 - 1].p = temp4;
    42 }
    43 scanf("%d %d",&s,&t);
    44 final[s - 1] = 1;
    45 for(i = 0; i < n; i ++)
    46 {
    47 dist[i].d = e[s - 1][i].d;
    48 dist[i].p = e[s - 1][i].p;
    49 }
    50 jump = s - 1;
    51 while(final[t - 1] != 1)//t结点未并入集合中
    52 {
    53 for(i = 0; i < n; i ++)
    54 {
    55 if(final[i] != 1)
    56 {
    57 minlength = dist[i].d;
    58 minprice = dist[i].p;
    59 if(jump != s - 1)
    60 {
    61 if(e[jump][i].d != -1)
    62 {
    63 templength = dist[jump].d + e[jump][i].d;
    64 tempprice = dist[jump].p + e[jump][i].p;
    65 if(templength != -1)
    66 {
    67 if(minlength == -1 || (minlength > templength) || (minlength == templength && minprice > tempprice))
    68 {
    69 minlength = templength;
    70 minprice = tempprice;
    71 }
    72 }
    73 }
    74 }
    75 dist[i].d = minlength;
    76 dist[i].p = minprice;
    77 }
    78 }
    79
    80 temp1 = dist[0].d;
    81 temp2 = dist[0].p;
    82 temp3 = 0;
    83 for(i = 1; i < n; i ++)
    84 {
    85 if(dist[i].d == -1 || final[i] == 1)
    86 {
    87 continue;
    88 }
    89 else if(final[temp3] == 1 || temp1 == -1 || dist[i].d < temp1 || (dist[i].d == temp1 && dist[i].p < temp2))
    90 {
    91 temp1 = dist[i].d;
    92 temp2 = dist[i].p;
    93 temp3 = i;
    94 }
    95 }
    96 final[temp3] = 1;
    97 jump = temp3;
    98 }
    99 printf("%d %d\n",dist[t - 1].d, dist[t - 1].p);
    100 }
    101 return 0;
    102 }
    103 /**************************************************************
    104 Problem: 1008
    105 User: qiushuiruyan
    106 Language: C
    107 Result: Accepted
    108 Time:20 ms
    109 Memory:8732 kb
    110 ****************************************************************/


    多说一下:关于最短路径问题,有SPFA算法更加有效,而且,该算法是由西南交通大学段凡丁于1994年发表的,有空去学习学习^_^

  • 相关阅读:
    LeetCode 【1】 Two Sum --001
    计算机网络-自定向下方法之应用层
    Android TextView自动换行、排列错乱问题及解决
    Android ScrollView内部组件设置android:layout_height="fill_parent"无效的解决办法
    Gson解析空字符串异常的处理
    AndroBench手机性能测试
    使用adb命令通过IP地址连接手机
    Android string.xml 添加特殊字符
    Android string资源 包含 数学符号等特殊字符 及 参数占位符
    Android Studio多渠道打包(二)
  • 原文地址:https://www.cnblogs.com/Rafy/p/2389814.html
Copyright © 2020-2023  润新知