• 城市之间的联系


    一 问题描述

    由于大部分道路在战争期间已被完全摧毁,所以两个城市之间可能没有路径,也没有环。已知道路状态,想知道任意两个城市之间是否存在路径。若答案是肯定的,则输出它们之间的最大距离。

    二 输入

    输入包含多个测试用例。每个测试用例第 1 行包含 3 个整数 n、m、c,n 表示城市数。编号为 1 到 n,接下来的 m 行,每行包含三个整数,i、j、k,表示城市 i 和城市 j 之间的道路,长度为 k,最后 c 行,每行包含 i、j 两个整数,表示查询城市 i 和城市 j 之间的最短路径

    三 输出

    对于每个查询,若两个城市之间没有路径,则输出“Not connected”,否则输出它们之间的最短路径。

    四 输入和输出样例

    1 输入样例

    5 3 2

    1 3 2

    2 4 3

    5 2 3

    1 4

    4 5

    2 输出样例

    Not connected

    6

    五 分析

    本问题的两点之间无环,且有可能不连通,有可能不是一棵树,而是由多棵树组成的森林。因此需要判断是否在同一棵树中,若不在同一棵树中,则输出 Not connected,否则可以使用求解最近公共祖先的 Tarjan 算法求解。

    六 设计

    1 根据输入的数据,采用链式前向星存储图。

    2 采用 Targan 算法离线处理所有查询,因为本问题的操作对象可能有多棵树,因此需要注意两个问题:

    a 修改 Targan 算法,引入一个 root 参数,用来判断待查询的两个节点是否在同一棵树中。

    b 对未访问过的节点再次执行 Targan 算法。

    3 将每个查询的两个节点之间的距离都存储在答案数组中。

    七 代码

    1. package com.platform.modules.alg.hdu2874;
    2. public class Hdu2874 {
    3. private final int maxn = 10000;
    4. private final int maxq = 1000000;
    5. Node e[] = new Node[2 * maxn];
    6. Query qe[] = new Query[2 * maxq];
    7. int ehead[] = new int[maxn];
    8. int dis[] = new int[maxn];
    9. int fa[] = new int[maxn];
    10. int ecnt;
    11. int vis[] = new int[maxn];
    12. int qhead[] = new int[maxn];
    13. int ans[] = new int[maxq];
    14. int qcnt;
    15. int n, m, c;
    16. void init() {
    17. ecnt = qcnt = 0;
    18. ehead = new int[maxn];
    19. for (int i = 0; i < ehead.length; i++) {
    20. ehead[i] = -1;
    21. }
    22. qhead = new int[maxn];
    23. for (int i = 0; i < qhead.length; i++) {
    24. qhead[i] = -1;
    25. }
    26. vis = new int[maxn];
    27. for (int i = 0; i < vis.length; i++) {
    28. vis[i] = -1;
    29. }
    30. for (int i = 0; i < e.length; i++) {
    31. e[i] = new Node();
    32. }
    33. for (int i = 0; i < qe.length; i++) {
    34. qe[i] = new Query();
    35. }
    36. }
    37. void add1(int u, int v, int w) {
    38. e[ecnt].to = v;
    39. e[ecnt].w = w;
    40. e[ecnt].next = ehead[u];
    41. ehead[u] = ecnt++;
    42. }
    43. void add2(int u, int v, int id) {
    44. qe[qcnt].id = id;
    45. qe[qcnt].to = v;
    46. qe[qcnt].next = qhead[u];
    47. qhead[u] = qcnt++;
    48. }
    49. int Find(int x) {
    50. if (x != fa[x])
    51. fa[x] = Find(fa[x]);
    52. return fa[x];
    53. }
    54. void LCA(int u, int deep, int root) {
    55. fa[u] = u;
    56. dis[u] = deep;
    57. vis[u] = root;
    58. for (int i = ehead[u]; i != -1; i = e[i].next) {
    59. int v = e[i].to;
    60. if (vis[v] == -1) {
    61. LCA(v, deep + e[i].w, root);
    62. fa[v] = u;
    63. }
    64. }
    65. for (int i = qhead[u]; i != -1; i = qe[i].next) {
    66. int v = qe[i].to;
    67. if (vis[v] == root)
    68. ans[qe[i].id] = dis[v] + dis[u] - 2 * dis[Find(v)];
    69. }
    70. }
    71. public String output = "";
    72. public String cal(String input) {
    73. String[] line = input.split("\n");
    74. String[] word = line[0].split(" ");
    75. n = Integer.parseInt(word[0]);
    76. m = Integer.parseInt(word[1]);
    77. c = Integer.parseInt(word[2]);
    78. int u, v, w;
    79. init();
    80. for (int i = 1; i <= m; i++) {
    81. String[] info = line[i].split(" ");
    82. u = Integer.parseInt(info[0]);
    83. v = Integer.parseInt(info[1]);
    84. w = Integer.parseInt(info[2]);
    85. add1(u, v, w);
    86. add1(v, u, w);
    87. }
    88. for (int i = 0; i < c; i++) {
    89. String[] query = line[i + m + 1].split(" ");
    90. u = Integer.parseInt(query[0]);
    91. v = Integer.parseInt(query[1]);
    92. ans[i] = -1;
    93. add2(u, v, i);
    94. add2(v, u, i);
    95. }
    96. for (int i = 1; i <= n; i++) {
    97. if (vis[i] == -1)
    98. LCA(i, 0, i);
    99. }
    100. for (int i = 0; i < c; i++) {
    101. if (ans[i] == -1) output += "Not connected\n";
    102. else output += ans[i] + "\n";
    103. }
    104. return output;
    105. }
    106. }
    107. // 边
    108. class Node {
    109. public int to; // 邻接点
    110. public int w; // 边权
    111. public int next; // 下一条边的下标
    112. }
    113. class Query {
    114. public int to;
    115. public int id; // 查询的编号
    116. public int next;
    117. }

     八 测试

     

  • 相关阅读:
    SpringBoot到底是什么?
    探索经典算法:贪心、分治、动态规划等
    微信超实用的小功能
    Java 集合中的排序算法浅析
    Linux 安全 - Capabilities机制
    我的创作纪念日
    完全掌握Nginx的终极指南:这篇文章让你对Nginx洞悉透彻
    软件测试,随机bug开发敷衍不修改?我.......差点又背锅了
    【解决】Github Pages搭建的网页访问加载缓慢
    【数据科学】Keras[Keras、数据、模型架构、预处理、审视模型、编译模型、模型训练、评估模型性能、预测、保存/加载模型、模型微调]
  • 原文地址:https://blog.csdn.net/chengqiuming/article/details/126907827