import std.stdio, std.getopt, std.random, std.range, std.string, std.conv;
import std.algorithm, std.container, std.datetime;

class LowLink {
	int n;
	int[][] g;
	int[] ord, low, root, cmp, used;
	this(int nn) {
		n = nn;
		g.length = ord.length = low.length = used.length = n;
		cmp.length = root.length = n;
	}

	void addEdge(int x, int y) {
		g[x] ~= y;
		g[y] ~= x;
	}

	int k;
	void dfs(int u, int b) {
		used[u] = 1;
		low[u] = ord[u] = k;
		k++;
		foreach (v; g[u]) {
			if (v == b) continue;
			if (!used[v]) {
				dfs(v, u);
				low[u] = min(low[u], low[v]);
			} else {
				low[u] = min(low[u], ord[v]);
			}
		}
	}

	int mc;
	void dfs2(int u, int d) {
		used[u] = 2;
		cmp[u] = d;
		mc = max(mc, d);
		foreach (v; g[u]) {
			if (used[v] == 2) continue;
			if (ord[u] < low[v]) {
				dfs2(v, d+1);
			} else {
				dfs2(v, d);
			}
		}
	}

	void exec() {
		k = mc = 0;
		int c = 0;
		foreach (i; 0..n) {
			if (!used[i]) {
				dfs(i, -1);
				dfs2(i, c);
				c = mc+1;
			}
		}
	}
}

int main() {
	int v, e;
	readf("%d %d\n", &v, &e);
	auto ll = new LowLink(v);
	alias Tuple!(int, int) P;
	P[] g;
	foreach (i; 0..e) {
		int a, b;
		readf("%d %d\n", &a, &b);
		ll.addEdge(a, b);
		g ~= P(a, b);
	}
	ll.exec();
	foreach (p; g) {
		if (ll.cmp[p[0]] != ll.cmp[p[1]]) {
			writeln(p[0], " ", p[1]);
		}
	}
    return 0;
}