奶牛聚会问题

x33g5p2x  于2022-07-11 转载在 其他  
字(2.3k)|赞(0)|评价(0)|浏览(254)

一 原问题链接

Silver Cow Party - POJ 3268 - Virtual Judge

https://vjudge.net/problem/POJ-3268

二 输入和输出

1 输入

第1行包含3个整数N、M、X。在第2~M+1行中,第 i+1 描述到了 i,有三个整数:Ai、Bi和Ti,表示从 Ai 农场到 Bi 农场需要 Ti 时间。

2 输出

单行输出母牛必须花费的时间的最大值。

三 输入和输出样例

1 输入样例

4 8 2

1 2 4

1 3 2

1 4 7

2 1 1

2 3 5

3 1 2

3 4 4

4 2 3

2 输出样例

10

四 分析

根据输入样例,共有4个农场、8条路,聚会地点在2号农场。母牛从4号农场出发,走一个回路 4-2-1-3-4 ,共计 10 个时间,该时间是所有母牛中来回时间最长的,如下图所示。

五 算法设计

因为母牛来回走的都是最短路径,所以先求从出发点到聚会点来回的最短路径之和,然后秋最大值即可。

1 从 i 号农场到聚会地点 X,相对于在反向图中从 X 到 i。

2 从聚会地点 X 返回 i 号农场,相对于在正向图中从 X 到 i。、

3 创建正向图和反向图,都把 X 作为源点,分别调用 SPFA 算法求正向图、反向图中源点到其他各个点最短时间 dis[i] 和 rdis[i],求最大和值。

六 算法实现

  1. package graph.poj3268;
  2. import java.util.LinkedList;
  3. import java.util.Queue;
  4. import java.util.Scanner;
  5. import java.util.concurrent.atomic.AtomicInteger;
  6. public class Poj3268 {
  7. static final int maxn = 10005;
  8. static final int inf = 0x3f3f3f3f;
  9. static int n;
  10. static int m;
  11. static int x;
  12. static AtomicInteger cnt = new AtomicInteger(0);
  13. static AtomicInteger rcnt = new AtomicInteger(0);
  14. static node e[] = new node[maxn];
  15. static node re[] = new node[maxn];
  16. static int head[] = new int[maxn];
  17. static int rhead[] = new int[maxn];
  18. static int dis[] = new int[maxn];
  19. static int rdis[] = new int[maxn];
  20. // 标记是否在队列中
  21. static boolean vis[] = new boolean[maxn];
  22. static {
  23. for (int i = 0; i < e.length; i++) {
  24. e[i] = new node();
  25. }
  26. for (int i = 0; i < re.length; i++) {
  27. re[i] = new node();
  28. }
  29. }
  30. static void add(node e[], int head[], int u, int v, int w, AtomicInteger cnt) {
  31. e[cnt.get()].to = v;
  32. e[cnt.get()].next = head[u];
  33. e[cnt.get()].w = w;
  34. head[u] = cnt.getAndIncrement();
  35. }
  36. static void spfa(node e[], int head[], int u, int dis[]) {
  37. Queue<Integer> q = new LinkedList<>();
  38. vis = new boolean[maxn];
  39. for (int i = 0; i < dis.length; i++) {
  40. dis[i] = inf;
  41. }
  42. vis[u] = true;
  43. dis[u] = 0;
  44. q.add(u);
  45. while (!q.isEmpty()) {
  46. int x = q.peek();
  47. q.poll();
  48. vis[x] = false;
  49. for (int i = head[x]; i >= 0; i = e[i].next) {
  50. if (dis[e[i].to] > dis[x] + e[i].w) {
  51. dis[e[i].to] = dis[x] + e[i].w;
  52. if (!vis[e[i].to]) {
  53. vis[e[i].to] = true;
  54. q.add(e[i].to);
  55. }
  56. }
  57. }
  58. }
  59. }
  60. public static void main(String[] args) {
  61. Scanner scanner = new Scanner(System.in);
  62. n = scanner.nextInt();
  63. m = scanner.nextInt();
  64. x = scanner.nextInt();
  65. for (int i = 0; i < head.length; i++) {
  66. head[i] = -1;
  67. }
  68. for (int i = 0; i < rhead.length; i++) {
  69. rhead[i] = -1;
  70. }
  71. int u, v, w;
  72. for (int i = 1; i <= m; i++) {
  73. u = scanner.nextInt();
  74. v = scanner.nextInt();
  75. w = scanner.nextInt();
  76. add(e, head, u, v, w, cnt);
  77. add(re, rhead, v, u, w, rcnt); // 反向图
  78. }
  79. spfa(e, head, x, dis);
  80. spfa(re, rhead, x, rdis);
  81. int ans = 0;
  82. for (int i = 1; i <= n; i++)
  83. ans = Math.max(ans, dis[i] + rdis[i]);
  84. System.out.println(ans);
  85. }
  86. }
  87. class node {
  88. int to;
  89. int w;
  90. int next;
  91. }

七 测试

绿色为输入,白色为输出。

八 参考

Java:通过引用传递int的最佳方法

相关文章