#include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <list>
#include <stack>
#include <string>
#include <functional>
#include <numeric>
#define _USE_MATH_DEFINES
#include <math.h>
#include <iomanip>
#include <map>
#include <set>
#include <cstdlib>
#include <bitset>
using namespace std;
#define INT_MAX 2147483647
#define INT_MIN (-2147483647 - 1)
#define INF (int)1e8
#define _INF (int)-1e8
#define INFLL (long long)1e14
#define _INFLL (long long)-1e14
#define Loop(i, n) for(int i = 0; i < (int)n; i++)
#define Loop1(i, n) for(int i = 1; i <= (int)n; i++)
#define Loopr(i, n) for(int i = (int)n - 1; i >= 0; i--)
#define Loopr1(i, n) for(int i = (int)n; i >= 1; i--)
#define bitmanip(m,val) static_cast<bitset<(int)m>>(val)
typedef long long int ll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;
typedef vector<ll> vll;
typedef vector<vector<ll>> vvll;
typedef vector<char> vc;
typedef vector<vector<char>> vvc;
typedef pair<int, int> P;

class Graph {
private:
	struct node {
		bool done;
		vi to, cost;
		int id, from;
		ll d;
		int pre, low;
		bool operator<(const node & another) const {
			return !(d != another.d ? d < another.d : id < another.id);
		}
	};
	vector<node> nodes;
	int ord, n;
	void reset() {
		Loop(i, n) {
			nodes[i].done = false;
			nodes[i].from = -1;
			nodes[i].d = INFLL;
		}
		fill(result.begin(), result.end(), 0);
	}
	void lowlink_dfs(int a, int root) {
		nodes[a].done = 1;
		nodes[a].pre = nodes[a].low = ord;
		ord++;
		int cnt = 0;
		Loop(i, nodes[a].to.size()) {
			int b = nodes[a].to[i];
			if (b == nodes[a].from) continue;
			if (!nodes[b].done) {
				nodes[b].from = a;
				lowlink_dfs(b, root);
				nodes[a].low = min(nodes[a].low, nodes[b].low);
				if (nodes[a].pre <= nodes[b].low) cnt++;
				if (nodes[a].pre < nodes[b].low) bridges.push_back({ a,b });
			}
			else {
				nodes[a].low = min(nodes[a].low, nodes[b].pre);
			}
		}
		if (cnt >(a == root ? 1 : 0)) arts.insert(a);
		return;
	}
public:
	vll result;
	vvll result2;
	vector<P> bridges;
	set<int> arts;
	Graph(vector<vector<P>> data) {
		n = data.size();
		result.resize(n);
		nodes.resize(n);
		ord = 0;
		Loop(i, n) {
			nodes[i] = { false,{},{}, i, -1, INFLL, -1, -1 };
			Loop(j, data[i].size()) {
				nodes[i].to.push_back(data[i][j].first);
				nodes[i].cost.push_back(data[i][j].second);
			}
		}
	}
	//mode=>dijkstra, !mode=>prim
	void mainalgo(int start, int mode) {
		reset();
		priority_queue<node> pq;
		nodes[start].d = 0;
		pq.push(nodes[start]);
		while (pq.size()) {
			node a = pq.top(); pq.pop();
			if (nodes[a.id].done) continue;
			nodes[a.id].done = true;
			Loop(j, a.to.size()) {
				node *b = &nodes[a.to[j]];
				if ((*b).done) continue;
				ll cand = (mode ? a.d : 0) + a.cost[j];
				if (cand < (*b).d) {
					(*b).d = cand;
					(*b).from = a.id;
					pq.push(*b);
				}
			}
		}
		Loop(i, n) result[i] = nodes[i].d;
	}
	//false=>negative_cycle
	bool bellman_ford(int start) {
		reset();
		nodes[start].d = 0;
		Loop(k, n) {
			Loop(i, n) {
				node *a = &nodes[i];
				Loop(j, (*a).to.size()) {
					node *b = &nodes[(*a).to[j]];
					if ((*a).d != INFLL && (*a).d + (*a).cost[j] < (*b).d) {
						(*b).d = (*a).d + (*a).cost[j];
						(*b).from = (*a).id;
						if (k == n - 1) return false;
					}
				}
			}
		}
		Loop(i, n) result[i] = nodes[i].d;
		return true;
	}
	//false=>negative_cycle
	bool warshall_floyd() {
		result2 = vvll(n, vll(n, INFLL));
		Loop(i, n) {
			result2[i][i] = 0;
			Loop(j, nodes[i].to.size()) {
				result2[i][nodes[i].to[j]] = nodes[i].cost[j];
			}
		}
		Loop(i, n) {
			Loop(j, n) {
				Loop(k, n) {
					if (result2[j][i] == INFLL || result2[i][k] == INFLL) continue;
					result2[j][k] = min(result2[j][k], result2[j][i] + result2[i][k]);
				}
			}
		}
		Loop(i, n) {
			if (result2[i][i] < 0) return false;
		}
		return true;
	}
	void find_bridges_and_arts() {
		Loop(i, nodes.size()) {
			if (!nodes[i].done) lowlink_dfs(i, i);
		}
		Loop(i, bridges.size()) {
			if (bridges[i].first > bridges[i].second) swap(bridges[i].first, bridges[i].second);
		}
		sort(bridges.begin(), bridges.end());
	}
};

int main() {
	int n, m;
	cin >> n >> m;
	vector<vector<P>> data(n);
	Loop(i, m) {
		int s, t; cin >> s >> t;
		data[s].push_back({ t,1 });
		data[t].push_back({ s,1 });
	}
	Graph g(data);
	g.find_bridges_and_arts();
	Loop(i, g.bridges.size()) {
		cout << g.bridges[i].first << " " << g.bridges[i].second << endl;
	}
	return 0;
}

Measured memory_bytes: 7688