#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

struct edge{
    int f, t;
};

const int V_MAX = (int)1e5 + 10;
vector<int> edges[V_MAX];
int ord[V_MAX];
int low[V_MAX];
bool used_v[V_MAX];
vector<edge> ans;

bool comp(edge e1, edge e2){
    if(e1.f == e2.f){
        return e1.t < e2.t;
    } else {
        return e1.f < e2.f;
    }
}

void dfs(int u, int prev, int k){
    low[u] = ord[u] = k;
    k += 1;
    used_v[u] = true;

    for(int i=0; i<edges[u].size(); i++){
        int next = edges[u][i];

        if(not used_v[next]){
            dfs(next, u, k);
            low[u] = min(low[u], low[next]);

            if(low[next] > ord[u]){
                edge e;
                e.f = min(u, next); e.t = max(u, next);
                ans.push_back(e);
            }
        } else if(prev != next){
            low[u] = min(low[u], ord[next]);
        }
    }
    return ;
}

int main(void){
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int v, e; 
    cin >> v >> e;

    for(int i=0; i<e; i++) {
        int a, b;
//        scanf("%d %d", &a, &b);
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }

    dfs(0, -1, 1);

    sort(ans.begin(), ans.end(), comp);
    for(int i=0; i<ans.size(); i++){
        cout << ans[i].f << " " << ans[i].t << "\n";
    }

    return 0;
}
### Prompt

Your challenge is to write a CPP solution to the following problem:

Find bridges of an undirected graph G(V, E).

A bridge (also known as a cut-edge) is an edge whose deletion increase the number of connected components.

Constraints

* 1 ≤ |V| ≤ 100,000
* 0 ≤ |E| ≤ 100,000
* The graph is connected
* There are no parallel edges
* There are no self-loops

Input


|V| |E|
s0 t0
s1 t1
:
s|E|-1 t|E|-1


, where |V| is the number of nodes and |E| is the number of edges in the graph. The graph nodes are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target nodes of i-th edge (undirected).

Output

A list of bridges of the graph ordered by name. For each bridge, names of its end-ponints, source and target (source < target), should be printed separated by a space. The sources should be printed ascending order, then the target should also be printed ascending order for the same source.

Examples

Input

4 4
0 1
0 2
1 2
2 3


Output

2 3


Input

5 4
0 1
1 2
2 3
3 4


Output

0 1
1 2
2 3
3 4

### Response

```cpp
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>

using namespace std;

struct edge{
    int f, t;
};

const int V_MAX = (int)1e5 + 10;
vector<int> edges[V_MAX];
int ord[V_MAX];
int low[V_MAX];
bool used_v[V_MAX];
vector<edge> ans;

bool comp(edge e1, edge e2){
    if(e1.f == e2.f){
        return e1.t < e2.t;
    } else {
        return e1.f < e2.f;
    }
}

void dfs(int u, int prev, int k){
    low[u] = ord[u] = k;
    k += 1;
    used_v[u] = true;

    for(int i=0; i<edges[u].size(); i++){
        int next = edges[u][i];

        if(not used_v[next]){
            dfs(next, u, k);
            low[u] = min(low[u], low[next]);

            if(low[next] > ord[u]){
                edge e;
                e.f = min(u, next); e.t = max(u, next);
                ans.push_back(e);
            }
        } else if(prev != next){
            low[u] = min(low[u], ord[next]);
        }
    }
    return ;
}

int main(void){
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int v, e; 
    cin >> v >> e;

    for(int i=0; i<e; i++) {
        int a, b;
//        scanf("%d %d", &a, &b);
        cin >> a >> b;
        edges[a].push_back(b);
        edges[b].push_back(a);
    }

    dfs(0, -1, 1);

    sort(ans.begin(), ans.end(), comp);
    for(int i=0; i<ans.size(); i++){
        cout << ans[i].f << " " << ans[i].t << "\n";
    }

    return 0;
}
```