• 最短路径专题3 最短距离-多边权


    题目:

    样例:

    输入
    1. 4 5 0 2
    2. 0 1 2 1
    3. 0 2 5 1
    4. 0 3 1 2
    5. 1 2 1 6
    6. 3 2 2 3

    输出
    3 5

    思路:

            根据题目意思,其实还是Dijkstra 的题目,不同的是,多了一个最少花费边权的这个点,多添加一个spend数组,结合dist数组即可,同样用堆优化方式更方便些。

    代码详解如下:

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #define endl '\n'
    7. #define int long long
    8. #define YES puts("YES")
    9. #define NO puts("NO")
    10. #define umap unordered_map
    11. #define INF 0x3f3f3f3f3f3f3f3f3f3f
    12. #define All(x) (x).begin(),(x).end()
    13. #pragma GCC optimize(3,"Ofast","inline")
    14. #define ___G std::ios::sync_with_stdio(false),cin.tie(0), cout.tie(0)
    15. using namespace std;
    16. const int N = 2e6 + 10;
    17. int n,k,start,last;
    18. int dist[N]; // 最短距离数组
    19. int spend[N]; // 最少花费边权数组
    20. bool st[N]; // 标记是否走动过
    21. // 定义存储 点,距离,边权 结构体
    22. struct Edge
    23. {
    24. int b; // 关系点
    25. int dis; // 距离
    26. int m; // 边权花费
    27. // 构造函数
    28. inline Edge(int _b,int _dis,int _m)
    29. {
    30. b = _b;
    31. dis = _dis;
    32. m = _m;
    33. }
    34. // 重载比较符号,方便堆排序
    35. inline bool operator<(const Edge&w)const
    36. {
    37. // 优先选择 最短距离,其次距离相等的时候,选择最少边权的花费
    38. if(dis != w.dis) return dis > w.dis;
    39. else return m > w.m;
    40. }
    41. };
    42. // 建立链表,e 存储的是关系点,w 存储的是距离,m 存储的是边权
    43. int h[N],w[N],m[N],ne[N],e[N],idx;
    44. inline void Add(int a,int b,int c,int d)
    45. {
    46. e[idx] = b,w[idx] = c,m[idx] = d,ne[idx] = h[a],h[a] = idx++;
    47. }
    48. inline void Dijkstra()
    49. {
    50. // 初始化最短距离数组和最少花费边权数组
    51. memset(dist,INF,sizeof dist);
    52. memset(spend,INF,sizeof spend);
    53. dist[start] = 0;
    54. spend[start] = 0;
    55. priority_queueq;
    56. // 存储起点
    57. q.push(Edge(start,0,0));
    58. while(q.size())
    59. {
    60. // 获取当前存储的边权距离关系
    61. Edge now = q.top();
    62. q.pop();
    63. int b = now.b; // 获取相应关系点
    64. int dis = now.dis; // 获取相应关系距离
    65. int spe = now.m; // 获取相应关系花费边权
    66. // 如果当前的 b 点走动过,进入下一个关系点的判断
    67. if(st[b]) continue;
    68. st[b] = true; // 标记当前点
    69. // 遍历连接的链表关系
    70. for(int i = h[b];i != -1;i = ne[i])
    71. {
    72. int j = e[i]; // 获取 与 b 点连接的 相应的关系点
    73. // 更新关系点的最短距离
    74. if(dist[j] > dis + w[i])
    75. {
    76. dist[j] = dis + w[i];
    77. // 由于一定会更新最短距离,所以花费也一定会更新
    78. spend[j] = spe + m[i];
    79. }else // 否则如果,最短距离相同,我们选择更新最少花费边权的
    80. if(dist[j] == dis + w[i] && spend[j] > spe + m[i]) spend[j] = spe + m[i];
    81. // 存储该关系点,进行下一次走动
    82. q.push(Edge(j,dist[j],spend[j]));
    83. }
    84. }
    85. }
    86. inline void solve()
    87. {
    88. cin >> n >> k >> start >> last;
    89. while(k--)
    90. {
    91. int a,b,c,d;
    92. cin >> a >> b >> c >> d;
    93. // 由于是无向图,所以添加两个点互相的链表
    94. Add(a,b,c,d);
    95. Add(b,a,c,d);
    96. }
    97. Dijkstra();
    98. // 输出答案
    99. cout << dist[last] << ' ' << spend[last] << endl;
    100. }
    101. signed main()
    102. {
    103. // 初始化链表
    104. memset(h,-1,sizeof h);
    105. // freopen("a.txt", "r", stdin);
    106. ___G;
    107. int _t = 1;
    108. // cin >> _t;
    109. while (_t--)
    110. {
    111. solve();
    112. }
    113. return 0;
    114. }

    最后提交:

  • 相关阅读:
    进程与线程的区别
    【ACM学习】【STL】顺序容器的特性比较(不包括array)
    【CSDN编程竞赛·第四期】个人参赛经历和个人建议
    erron变量、strerror函数 和 perror 函数
    OpenCV实战(30)——OpenCV与机器学习的碰撞
    windows下使用FFmpeg开源库进行视频编解码完整步聚
    525. 连续数组 (前缀和 + 哈希)
    《HelloGitHub》第 94 期
    熊市下PLATO如何通过Elephant Swap,获得溢价收益?
    Win:确认操作系统激活状态
  • 原文地址:https://blog.csdn.net/hacker_51/article/details/133528877