图的底部问题

x33g5p2x  于2022-07-04 转载在 其他  
字(2.0k)|赞(0)|评价(0)|浏览(242)

一 原问题链接

The Bottom of a Graph - POJ 2553 - Virtual Judge

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

二 输入和输出

1 输入

输入包含几个测试用例,每个测试用例都对应一个有向图G,每个测试用例都以整数 v开始,表示图 G 的节点数,节点编号为 1~v。接下来是非负整数e,然后是e对编号v1、w1、......ve、we,其中(vi,wi)表示一条边。在最后一个测试用例后跟着一个0.

2 输出

单行输出图底部的所有 sink 节点。如果没有,则输出一个空行。

三 输入和输出样例

1 输入样例

3 3

1 3 2 3 3 1

2 1

1 2

0

2 输出样例

1 3

2

四 问题分析

输入样例1,构建的图如下,图中 sink 节点为 1 和 3。

思路:求解强连通分量,并对强连通分量缩点,计算缩点的出度,出度为0 的强连通分量中的所有节点均为 sink 节点。

五 算法设计

1 先采用 Targan 算法求解有向图的强连通分量,标记强连通分量号。

2 检查每个节点 u 的每个邻接点 v,若强连通分量不同,则将 u 的连通分量号的出度加1。

3 检查每个节点 u,若其连通分量号的出度为0,则输出该节点。

六 代码

  1. package graph.poj553;
  2. import java.util.Scanner;
  3. import java.util.Stack;
  4. public class POJ2553 {
  5. static final int maxn = 1000 + 5;
  6. static int n;
  7. static int m;
  8. static int head[];
  9. static int belong[];
  10. static int out[];
  11. static int cnt;
  12. static int id;
  13. static int low[];
  14. static int dfn[];
  15. static int num;
  16. static Edge e[] = new Edge[maxn << 1];
  17. static Stack<Integer> s = new Stack<>();
  18. static boolean ins[] = new boolean[maxn];
  19. static {
  20. for (int i = 0; i < e.length; i++) {
  21. e[i] = new Edge();
  22. }
  23. }
  24. static void add(int u, int v) { // 添加一条边u--v
  25. e[++cnt].next = head[u];
  26. e[cnt].to = v;
  27. head[u] = cnt;
  28. }
  29. static void tarjan(int u) { // 求强连通分量
  30. low[u] = dfn[u] = ++num;
  31. ins[u] = true;
  32. s.push(u);
  33. for (int i = head[u]; i != 0; i = e[i].next) {
  34. int v = e[i].to;
  35. if (dfn[v] == 0) {
  36. tarjan(v);
  37. low[u] = Math.min(low[u], low[v]);
  38. } else if (ins[v]) {
  39. low[u] = Math.min(low[u], dfn[v]);
  40. }
  41. }
  42. if (low[u] == dfn[u]) {
  43. int v;
  44. do {
  45. v = s.peek();
  46. s.pop();
  47. belong[v] = id;
  48. ins[v] = false;
  49. } while (v != u);
  50. id++;
  51. }
  52. }
  53. static void init() {
  54. head = new int[maxn];
  55. low = new int[maxn];
  56. dfn = new int[maxn];
  57. ins = new boolean[maxn];
  58. belong = new int[maxn];
  59. out = new int[maxn];
  60. cnt = num = 0;
  61. id = 1;
  62. }
  63. public static void main(String[] args) {
  64. Scanner scanner = new Scanner(System.in);
  65. while (true) {
  66. n = scanner.nextInt();
  67. if (n == 0) {
  68. return;
  69. }
  70. m = scanner.nextInt();
  71. init();
  72. while (m-- != 0) {
  73. int u, v;
  74. u = scanner.nextInt();
  75. v = scanner.nextInt();
  76. add(u, v);
  77. }
  78. for (int i = 1; i <= n; i++)
  79. if (dfn[i] == 0)
  80. tarjan(i);
  81. for (int u = 1; u <= n; u++)
  82. for (int i = head[u]; i > 0; i = e[i].next) {
  83. int v = e[i].to;
  84. if (belong[u] != belong[v])
  85. out[belong[u]]++;
  86. }
  87. int flag = 1;
  88. System.out.println();
  89. for (int i = 1; i <= n; i++)
  90. if (out[belong[i]] == 0) {
  91. if (flag == 1)
  92. flag = 0;
  93. else
  94. System.out.print(" ");
  95. System.out.print(i);
  96. }
  97. }
  98. }
  99. }
  100. class Edge {
  101. int to;
  102. int next;
  103. }

七 测试

绿色为输入,白色为输出

相关文章