#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <queue>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <fstream>
#include <stdio.h>
#include <complex>
#include <cstdint>
#include <tuple>
#include <numeric>
#define M_PI       3.14159265358979323846
#ifdef LOCAL
#include <sys/types.h>
#include <sys/timeb.h>
#include <intrin.h> 
#include <thread>
#else
#include <sys/time.h>
#endif

using namespace std;

//conversion
//------------------------------------------
inline int toInt(string s) { int v; istringstream sin(s); sin >> v; return v; }
template<class T> inline string toString(T x) { ostringstream sout; sout << x; return sout.str(); }

//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;

//container util
//------------------------------------------
#define ALL(a)  (a).begin(),(a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define MT make_tuple
#define SZ(a) int((a).size())
#define EACH(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define EXIST(s,e) ((s).find(e)!=(s).end())
#define SORT(c) sort((c).begin(),(c).end())
#define FILL(a, x) memset(a, x, sizeof(a))

//repetition
//------------------------------------------
#define FOR(i,s,n) for(int i=s;i<(int)n;++i)
#define REP(i,n) FOR(i,0,n)

const int N = 100000;
int idx[N];
int lowlink[N];
bool onstack[N];

struct edge {
	int to;
	edge(int _to) : to(_to) {};
};
using node = vector<edge>;
using graph = vector<node>;

void visit(graph &g,int node, int parent, int &ord, VI & order, vector<PII> &bridges, VVI &bcc, stack<int> &S, vector<bool> &inS, stack<int> &roots) {
	order[node] = ord++;
	S.push(node); inS[node] = true;
	roots.push(node);
	for (auto e : g[node]) {
		if (order[e.to] == -1) {
			visit(g, e.to, node, ord, order, bridges, bcc, S, inS, roots);
		}
		else if( parent != e.to && inS[e.to]){
			while (order[roots.top()] > order[e.to])roots.pop();		
		}
	}
	if (node == roots.top()) {
		bridges.PB(PII(min(node, parent), max(node, parent)));
		bcc.PB(VI());
		while (1) {
			int cur = S.top(); S.pop(); inS[cur] = false;
			bcc.back().PB(cur);
			if (cur == node)break;
		}
		roots.pop();
	}
}

void bridge(graph &g, vector<PII> &bridges, VVI &bcc) {
	int n = g.size();
	VI order(n, -1);
	vector<bool> inS(n);
	stack<int> roots, S;
	int ord = 0;
	REP(i, n) {
		if (order[i] == -1) {
			visit(g, i, -1, ord, order, bridges, bcc, S, inS, roots);
			bridges.pop_back();
		}
	}
}

int main(){
	int n, m;
	scanf("%d%d", &n, &m);
	graph g(n);
	REP(i, m) {
		int x, y;
		scanf("%d%d", &x, &y);
		g[x].PB(y);
		g[y].PB(x);
	}
	vector<PII> bridges;
	VVI bcc;
	bridge(g, bridges, bcc);
	SORT(bridges);
	for (auto e : bridges) printf("%d %d\n", e.first, e.second);
	return 0;
}


Measured memory_bytes: 5384