1
+ #include < bits/stdc++.h>
2
+ using namespace std ;
3
+ typedef long long ll;
4
+
5
+ #define MOD 1000000007LL
6
+ #define EPS 1e-9
7
+ #define io ios_base::sync_with_stdio (false );cin.tie(NULL );
8
+ #define M_PI 3.14159265358979323846
9
+
10
+ const int MAXN = 1e5 +5 ;
11
+ vector<int > adj[MAXN], tree[MAXN]; // The bridge edge tree formed from the given graph.
12
+ int disc[MAXN], low[MAXN], vis[MAXN];
13
+ queue<int > Q[MAXN];
14
+ int currTime, n, m, cmpno = 1 ;
15
+ map<pair<int , int >, int > bridge;
16
+
17
+ void dfs0 (int u, int parent){
18
+ vis[u] = true ;
19
+ disc[u] = low[u] = currTime++;
20
+ for (auto v : adj[u]){
21
+ if (v == parent) continue ;
22
+ if (!vis[v]){
23
+ dfs0 (v, u);
24
+ low[u] = min (low[u], low[v]);
25
+ if (low[v] > disc[u]){
26
+ bridge[{u, v}] = 1 ;
27
+ bridge[{v, u}] = 1 ;
28
+ }
29
+ }else {
30
+ low[u] = min (low[u], disc[v]);
31
+ }
32
+ }
33
+ return ;
34
+ }
35
+
36
+ bool isBridge (int u, int v){
37
+ return (bridge[{u, v}] == 1 && bridge[{v, u}] == 1 );
38
+ }
39
+
40
+ void dfs1 (int u){
41
+ int currcmp = cmpno;
42
+ Q[currcmp].push (u);
43
+ vis[u] = true ;
44
+ while (!Q[currcmp].empty ()){
45
+ int u = Q[currcmp].front ();
46
+ Q[currcmp].pop ();
47
+ for (auto v : adj[u]){
48
+ if (vis[v]) continue ;
49
+ if (isBridge (u, v)){
50
+ cmpno++;
51
+ tree[currcmp].push_back (cmpno);
52
+ tree[cmpno].push_back (currcmp);
53
+ dfs1 (v);
54
+ }else {
55
+ Q[currcmp].push (v);
56
+ vis[v] = true ;
57
+ }
58
+ }
59
+ }
60
+ return ;
61
+ }
62
+
63
+ int main (){
64
+ io;
65
+ cin >> n >> m;
66
+ for (int i = 0 ;i < m; i++){
67
+ int a, b;
68
+ cin >> a >> b;
69
+ adj[a].push_back (b);
70
+ adj[b].push_back (a);
71
+ }
72
+ dfs0 (1 , -1 ); // To find bridges
73
+ memset (vis, false , sizeof vis);
74
+ dfs1 (1 ); // To build bridge tree
75
+ for (int i = 1 ;i <= cmpno; i++){
76
+ for (int j = 0 ;j < tree[i].size (); j++)
77
+ cout << i << " " << tree[i][j] << endl;
78
+ }
79
+ return 0 ;
80
+ }
0 commit comments