fork download
  1. #include <bits/stdc++.h>
  2.  
  3. using namespace std;
  4.  
  5. typedef long long ll;
  6. typedef pair<int, int> ii;
  7.  
  8. const int INF = 1e9;
  9. const ll LINF = 1e18;
  10.  
  11. const int N = 1e4 + 5;
  12.  
  13. int n, m;
  14. vector<int> adj[N];
  15.  
  16. int timer;
  17. int tin[N]; // tin[u] = thời gian mà dfs đi vào đỉnh u
  18. int low[N]; // low[u] = giá trị tin[v] của đỉnh v có tin[v] nhỏ nhất mà u đến được và chỉ sử dụng tối đa 1 cạnh ngược
  19. int cnt_cutpoint; // Số đỉnh khớp
  20. int cnt_bridge; // Số cạnh cầu
  21.  
  22. void dfs(int u, int p) {
  23. tin[u] = low[u] = ++timer;
  24.  
  25. int child = 0; // Số đỉnh con của u trên cây dfs
  26. bool is_cutpoint = false;
  27. for (int v : adj[u]) {
  28. if (v == p) continue;
  29. if (!tin[v]) {
  30. // (u, v) là cạnh của cây dfs
  31. child++;
  32. dfs(v, u);
  33. low[u] = min(low[u], low[v]);
  34. if (low[v] > tin[u]) cnt_bridge++;
  35. if (low[v] >= tin[u] && p != -1) is_cutpoint = true; // trường hợp u không phải nút gốc của cây dfs
  36. }
  37. else {
  38. // (u, v) là cạnh ngược
  39. low[u] = min(low[u], tin[v]);
  40. }
  41. }
  42.  
  43. if (p == -1) { // trường hợp u là nút gốc của cây dfs
  44. is_cutpoint = (child >= 2);
  45. }
  46.  
  47. cnt_cutpoint += is_cutpoint;
  48. }
  49.  
  50. int main() {
  51. ios::sync_with_stdio(false);
  52. cin.tie(nullptr);
  53. cin >> n >> m;
  54. for (int i = 0; i < m; i++) {
  55. int u, v;
  56. cin >> u >> v;
  57. adj[u].push_back(v);
  58. adj[v].push_back(u);
  59. }
  60.  
  61. timer = 0;
  62. cnt_cutpoint = cnt_bridge = 0;
  63. for (int u = 1; u <= n; u++) {
  64. if (!tin[u]) dfs(u, -1);
  65. }
  66.  
  67. cout << cnt_cutpoint << ' ' << cnt_bridge << '\n';
  68. }
Success #stdin #stdout 0.01s 5276KB
stdin
10 12
1 10
10 2
10 3
2 4
4 5
5 2
3 6
6 7
7 3
7 8
8 9
9 7
stdout
4 3