fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. const int maxN = 10010;
  6.  
  7. int n, m;
  8. bool khop[maxN];
  9. int timeDfs = 0, bridge = 0;
  10. int low[maxN], num[maxN];
  11. vector <int> g[maxN];
  12.  
  13.  
  14. /// dinh u ma chua dfs toi : num[u] = 0, low[u] = 0;
  15.  
  16. ///
  17.  
  18. void dfs(int u, int p) {
  19. int child = 0; // Số lượng con trực tiếp của đỉnh u trong cây DFS
  20. num[u] = low[u] = ++timeDfs;
  21.  
  22. /// num[u] : số thứ tự mà đỉnh u được dfs tới
  23. /// low[u] = num[v] với v là đỉnh sở hữu num[v] nhỏ nhất sao cho u có thể tới v thông qua quá trình dfs
  24.  
  25. for (int v : g[u]) {
  26. if (v == p) continue;
  27. if (!num[v]) {
  28.  
  29. dfs(v, u);
  30.  
  31. /// khi này ta sẽ biết được low[v]
  32.  
  33. low[u] = min(low[u], low[v]);
  34.  
  35. /// thằng v vươn tới đâu thì u cũng có thể vươn tới đó
  36.  
  37.  
  38. if (low[v] == num[v]) {
  39. /// cạnh u - v là cầu
  40.  
  41. /// bởi vì v ko thể tìm được chỗ khác để nối tới
  42.  
  43. /// khi mà bị mất đi cạnh u - v
  44. bridge++;
  45. }
  46. child++;
  47.  
  48. /// child tại đỉnh u đóng vai trò là số lần
  49. /// dfs tới các đỉnh con
  50.  
  51.  
  52. /// u = pre = 1
  53. /// num[1] = 1
  54. /// đẫn tới low[v] >= num[1] hiển nhiên sẽ xảy ra
  55. /// nên ta phải xét riêng trường hợp này
  56.  
  57. if (u == p) { // Nếu u là đỉnh gốc của cây DFS
  58. if (child >= 2) khop[u] = true;
  59. }
  60. else
  61. if (low[v] >= num[u]) khop[u] = true;
  62.  
  63. }
  64. else if (num[v] != 0) {
  65.  
  66.  
  67. /// em đang đỉnh u
  68.  
  69. /// low[u]
  70.  
  71. /// e có thể vươn tới đỉnh v mà đỉnh v nó đã được gán low[v], num[v] trước đó
  72.  
  73. /// suy ra v được dfs tới trước u
  74.  
  75. /// suy ra nó là cung ngược
  76. low[u] = min(low[u], num[v]);
  77. }
  78. }
  79. }
  80.  
  81. int main() {
  82. cin >> n >> m;
  83. for (int i = 1; i <= m; i++) {
  84. int u, v;
  85. cin >> u >> v;
  86. g[u].push_back(v);
  87. g[v].push_back(u);
  88. }
  89.  
  90. dfs(1, 1);
  91.  
  92. for (int i = 1; i <= n; i++)
  93. if (!num[i]) dfs(i, i);
  94.  
  95. int cntJoint = 0;
  96. for (int i = 1; i <= n; i++) cntJoint += khop[i];
  97.  
  98. cout << cntJoint << ' ' << bridge;
  99. }
  100.  
Success #stdin #stdout 0s 5288KB
stdin
Standard input is empty
stdout
0 0