解法一:Dijkstra最短路径

相比经典的最短路问题,多了一个求解方案数的步骤,在进行松弛操作时,如果遇到路径更短的方案,就用其方案数更新,如果路径长度相等,则加上其方案数。
注意本题是无向图。拿堆优化写的一直WA,没找到原因,心累😪

  1. import java.io.*;
  2. import java.util.Arrays;
  3. import java.util.Comparator;
  4. import java.util.PriorityQueue;
  5. class Main {
  6. public static void main(String[] args) throws IOException {
  7. // StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
  8. BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
  9. PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
  10. String[] input = in.readLine().split(" ");
  11. final int N = Integer.parseInt(input[0]);
  12. final int M = Integer.parseInt(input[1]);
  13. final int src = Integer.parseInt(input[2]);
  14. final int dst = Integer.parseInt(input[3]);
  15. // 方案数
  16. int[] solutions = new int[N];
  17. Point[] points = new Point[N];
  18. for (int i = 0; i < N; ++i) {
  19. points[i] = new Point();
  20. }
  21. input = in.readLine().split(" ");
  22. // 每个城市的救援队员人数
  23. int[] values = new int[N];
  24. for (int i = 0; i < N; ++i) {
  25. values[i] = Integer.parseInt(input[i]);
  26. }
  27. // 邻接矩阵
  28. int[][] graph = new int[N][N];
  29. for (int i = 0; i < N; ++i) {
  30. Arrays.fill(graph[i], 0x3f3f3f3f);
  31. }
  32. for (int i = 0, u, v, dis; i < M; ++i) {
  33. input = in.readLine().split(" ");
  34. u = Integer.parseInt(input[0]);
  35. v = Integer.parseInt(input[1]);
  36. dis = Integer.parseInt(input[2]);
  37. graph[u][v] = dis;
  38. graph[v][u] = dis;
  39. }
  40. points[src].dis = 0;
  41. points[src].val = values[src];
  42. solutions[src] = 1;
  43. for (int i = 0; i < N; ++i) {
  44. int start = -1;
  45. for (int j = 0; j < N; ++j) {
  46. if ((!points[j].isVisited) && ((start == -1) || (points[start].dis > points[j].dis))) {
  47. start = j;
  48. }
  49. }
  50. points[start].isVisited = true;
  51. for (int j = 0; j < N; ++j) {
  52. if (points[j].dis > points[start].dis + graph[start][j]) {
  53. points[j].dis = points[start].dis + graph[start][j];
  54. solutions[j] = solutions[start];
  55. points[j].val = points[start].val + values[j];
  56. } else if (points[j].dis == points[start].dis + graph[start][j]) {
  57. solutions[j] += solutions[start];
  58. points[j].val = Math.max(points[j].val, values[j] + points[start].val);
  59. }
  60. }
  61. }
  62. System.out.println(solutions[dst] + " " + points[dst].val);
  63. // out.flush();
  64. }
  65. }
  66. class Point {
  67. // 到源点的最小距离
  68. int dis;
  69. // 到达该点的最大救援队员的人数
  70. int val;
  71. // 是否访问过
  72. boolean isVisited;
  73. Point() {
  74. dis = 0x3f3f3f3f;
  75. val = 0;
  76. isVisited = false;
  77. }
  78. }