##### Preview:
```#include <iostream>
#include <set>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <iterator>
// #include<bits/stdc++.h>
using namespace std;
#define forn(i, a, n) for (int i = a; i < n; i++)
#define MAXN 1000000
#define MOD 1000000007
#define int long long
#define tc    \
int t;    \
cin >> t; \
while (t--)
#define TC size(arr) / size(arr[0])
#define mp make_pair
#define Krishna cin.tie(NULL);

int Time = 0;
vector<pair<int, int>> br;
set<pair<int, int>> res;

vector<int> low, disc;

void dfsBR(int u, int p)
{
low[u] = disc[u] = ++Time;
{
if (v == p)
continue; // we don't want to go back through the same path.
// if we go back is because we found another way back
if (!disc[v])
{
res.insert({u, v});
// if V has not been discovered before
dfsBR(v, u);          // recursive DFS call
if (disc[u] < low[v]) // condition to find a bridge
br.push_back({u, v});

low[u] = min(low[u], low[v]); // low[v] might be an ancestor of u
}
else // if v was already discovered means that we found an ancestor
{
if (low[u] >= disc[v])
{
low[u] = min(low[u], disc[v]); // finds the ancestor with the least discovery time
res.insert({u, v});

}else{
if(res.find({v,u})==res.end()){
res.insert({u,v});
}
}

}
}
}

void BR()
{
low = disc = vector<int>(adj.size(), 0);
Time = 0;
for (int u = 0; u < adj.size(); u++)
{
if (!disc[u])
{
dfsBR(u, u);
}
}
}

void solve()
{
int n, m;
cin >> n >> m;
forn(i, 0, m)
{
int u, v;
cin >> u >> v;
u--, v--;
}

BR();

if (br.size())
{
cout << 0 << endl;
return;
}

// cout<<br.size()<<endl;
for (auto &x : res)
{
cout << x.first + 1 << " " << x.second + 1 << endl;
}
}
int32_t main()
{