#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/rope>
using namespace std;
using namespace __gnu_pbds;
using namespace __gnu_cxx;
#define int long long
using ll = long long;
mt19937_64 rd(time(0));
template <class K, class C = less<>> using paring_heap = __gnu_pbds::priority_queue<K, C>;
template <class K, class V = null_type, class C = less<>> using rb_tree = tree<K, V, C, rb_tree_tag, tree_order_statistics_node_update>;
template <class T, class ... A> void debug(const T & t, const A & ... a) { cerr << "[" << t, ((cerr << ", " << a), ...), cerr << "]\n"; }
const ll mod = [](bool n) { return n ? 998244353 : 1e9 + 7; } (1);
template <ll mod = mod> ll binpow(ll a, ll b, ll res = 1) {
for (a %= mod; b; b >>= 1, (a *= a) %= mod) {
if (b & 1) (res *= a) %= mod;
}
return res;
}
vector<signed> inv, fact, invfa;
auto INIT_FACT = ([](int n) {
inv = fact = invfa = vector<signed>(n + 1, 1);
for (int i = 2; i <= n; i++) {
fact[i] = (ll)fact[i - 1] * i % mod, invfa[i] = (ll)invfa[i - 1] * (inv[i] = (mod - mod / i) * inv[mod % i] % mod);
}
} (0), true);
ll C(int n, int m) { return min(n - m, m) < 0 ? 0 : (ll)fact[n] * invfa[m] % mod * invfa[n - m] % mod; }
ll P(int n, int m) { return min(n - m, m) < 0 ? 0 : (ll)fact[n] * invfa[n - m] % mod; }
ll LC(ll n, ll m) { return !m ? 1 : C(n % mod, m % mod) * LC(n / mod, m / mod) % mod; }
template <class type = int, int len = 2> struct Tarjan_bridge : vector<vector<signed>> {
vector<array<type, len + 1>> e; // {u, v, is_bridge}
vector<signed> dfn, dcc, low;
vector dc = {};
Tarjan_bridge(int n, int m) : vector(n), e(m), dfn(n), dcc(n), low(n) {}
void operator()(stack<signed> s = {}, int tot_dfn = 0) { // !! 会包含 0 , 可能 0 会成孤岛
for (int rt = 0; rt < size(); rt++, s = {}) {
auto self = [&](auto && self, int u, int from) -> void { // 用 from 而不用 fa 因为可能重边
s.emplace(u), dfn[u] = low[u] = ++tot_dfn;
for (auto & i : at(u)) {
int v = e[i][0] ^ e[i][1] ^ u;
if (!dfn[v]) {
self(self, v, i), low[u] = min(low[u], low[v]);
if (low[v] > dfn[u]) e[i].back() = true; // 是桥
} else if (i != from) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) for (dc.emplace_back(); !dc.back().size() || dc.back().back() != u; ) {
dcc[s.top()] = dc.size() - 1, dc.back().emplace_back(s.top()), s.pop();
}
};
if (!dfn[rt]) self(self, rt, -1);
}
}
};
void QAQ() {
int n, m;
cin >> n >> m;
Tarjan_UnDir adj(n + 1, m);
for (int i = 0, u, v; i < m; i++) {
cin >> u >> v;
adj[u].push_back(i), adj[v].push_back(i);
adj.e[i] = {u, v};
}
adj();
for (auto & [u, v, bri] : adj.e) {
if (bri) cout << u << " " << v << "\n";
}
}
signed main() {
cin.tie(0) -> sync_with_stdio(0);
int t = 1;
// cin >> t;
for (cout << fixed << setprecision(12); t--; QAQ());
}