关键路径实现

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

 一 拓扑图

二 代码

  1. package graph.criticalPath;
  2. import java.util.Scanner;
  3. import java.util.Stack;
  4. public class CriticalPath {
  5. static final int maxn = 10010;
  6. static final int maxe = 50010;
  7. static int n;
  8. static int m;
  9. static int cnt;
  10. static int head[] = new int[maxn]; // 链式前向星头
  11. static int in[] = new int[maxn]; // 入度
  12. static int topo[] = new int[maxn]; //拓扑序列
  13. static int ve[] = new int[maxn]; // 事件vi的最早发生时间
  14. static int vl[] = new int[maxn]; // 事件vi的最迟发生时间
  15. static Stack<Integer> s = new Stack<>();
  16. static node[] e = new node[maxe];
  17. static {
  18. for (int i = 0; i < e.length; i++) {
  19. e[i] = new node();
  20. }
  21. }
  22. static void add(int u, int v, int w) {
  23. e[cnt].to = v;
  24. e[cnt].next = head[u];
  25. head[u] = cnt;
  26. e[cnt++].w = w;
  27. }
  28. // 拓扑排序
  29. static boolean TopoSort() {
  30. int cnt = 0;
  31. for (int i = 0; i < n; i++)
  32. if (in[i] == 0)
  33. s.push(i);
  34. while (!s.empty()) {
  35. int u = s.peek();
  36. s.pop();
  37. topo[cnt++] = u;
  38. for (int i = head[u]; i != -1; i = e[i].next) {
  39. int v = e[i].to;
  40. if (--in[v] == 0)
  41. s.push(v);
  42. }
  43. }
  44. if (cnt < n) return false; // 该有向图有回路
  45. return true;
  46. }
  47. static boolean CriticalPath() { // 关键路径
  48. if (TopoSort()) {
  49. System.out.println("拓扑序列为:");
  50. for (int i = 0; i < n; i++) // 输出拓扑序列
  51. System.out.print(topo[i] + "\t");
  52. System.out.println();
  53. } else {
  54. System.out.println("该图有环,无拓扑序列!");
  55. return false;
  56. }
  57. for (int i = 0; i < n; i++) // 初始化最早发生时间为0
  58. ve[i] = 0;
  59. // 按拓扑次序求每个事件的最早发生时间
  60. for (int j = 0; j < n; j++) {
  61. int u = topo[j]; // 取得拓扑序列中的顶点
  62. for (int i = head[u]; i != -1; i = e[i].next) {
  63. int v = e[i].to, w = e[i].w;
  64. if (ve[v] < ve[u] + w)
  65. ve[v] = ve[u] + w;
  66. }
  67. }
  68. for (int i = 0; i < n; i++) //初始化每个事件的最迟发生时间为ve[n]
  69. vl[i] = ve[n - 1];
  70. for (int j = n - 1; j >= 0; j--) {//按逆拓扑序求每个事件的最迟发生时间
  71. int u = topo[j]; //取得拓扑序列中的顶点
  72. for (int i = head[u]; i != -1; i = e[i].next) {
  73. int v = e[i].to, w = e[i].w;
  74. if (vl[u] > vl[v] - w)
  75. vl[u] = vl[v] - w;
  76. }
  77. }
  78. System.out.println("事件的最早发生时间和最迟发生时间:");
  79. for (int i = 0; i < n; i++)
  80. System.out.println(ve[i] + "\t" + vl[i]);
  81. System.out.println("关键活动路径为:");
  82. for (int u = 0; u < n; u++) { //每次循环针对vi为活动开始点的所有活动
  83. for (int i = head[u]; i != -1; i = e[i].next) {
  84. int v = e[i].to, w = e[i].w;
  85. int e = ve[u]; // 计算活动<vi, vj>的最早开始时间e
  86. int l = vl[v] - w; // 计算活动<vi, vj>的最迟开始时间l
  87. if (e == l) // 若为关键活动,则输出<vi, vj>
  88. System.out.println("<" + u + "," + v + ">");
  89. }
  90. }
  91. return true;
  92. }
  93. public static void main(String[] args) {
  94. int u, v, w;
  95. Scanner scanner = new Scanner(System.in);
  96. n = scanner.nextInt();
  97. m = scanner.nextInt();
  98. for (int i = 0; i < head.length; i++) {
  99. head[i] = -1;
  100. }
  101. for (int i = 0; i < m; i++) {
  102. u = scanner.nextInt();
  103. v = scanner.nextInt();
  104. w = scanner.nextInt();
  105. add(u, v, w);
  106. in[v]++;
  107. }
  108. CriticalPath();
  109. }
  110. }
  111. class node {
  112. int to;
  113. int w;
  114. int next;
  115. }

三 测试

相关文章