#include <bits/stdc++.h>
using namespace std;
#define int long long   // <-----!!!!!!!!!!!!!!!!!!!

#define rep(i,n) for (int i=0;i<(n);i++)
#define rep2(i,a,b) for (int i=(a);i<(b);i++)
#define rrep(i,n) for (int i=(n)-1;i>=0;i--)
#define rrep2(i,a,b) for (int i=(b)-1;i>=(a);i--)
#define all(a) (a).begin(),(a).end()
#define rall(a) (a).rbegin(),(a).rend()
#define printV(v) for(auto&& x : v){cerr << x << " ";} cerr << endl
#define printVV(vv) for(auto&& v : vv){for(auto&& x : v){cerr << x << " ";}cerr << endl;}
#define printP(p) cerr << p.first << " " << p.second << endl
#define printVP(vp) for(auto&& p : vp) printP(p);

typedef long long ll;
typedef pair<int, int> Pii;
typedef tuple<int, int, int> TUPLE;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<vvi> vvvi;
typedef vector<Pii> vp;
const int inf = 1e9;
const int mod = 1e9 + 7;
typedef vector<vector<int>> Graph;
typedef pair<int, int>      Edge;   // (a < b: undirected)

class BICC {
private:
    const int n;

    Graph G;
    vi depth;
    vi par;
    map<Edge, int> imosEdge;
    map<Edge, int> EdgeType;
    enum {UNUSED, USED_DFS, BRIDGE};
    vector<Edge> bridges;

	vi cmp;
	int num_cc;
	vi size_of_vertex;
	Graph G_cc;
public:
    BICC(int _n) : n(_n), G(_n), depth(_n, -1), par(_n, -1), cmp(_n, -1), num_cc(0) {}
    Edge getEdge(int a, int b) {
        if (a > b) swap(a, b);
        return Edge(a, b);
    }
    void updateEdgeType(int a, int b, int type) {
        if (a < 0 || b < 0) return;
        EdgeType[getEdge(a, b)] = type;
    }
    void addEdge(int a, int b) {
        G[a].emplace_back(b);
        G[b].emplace_back(a);
        updateEdgeType(a, b, UNUSED);
    }
    void dfsTreeConstruct(int v, int pre) {
        if (depth[v] != -1) return;
        depth[v] = (pre == -1 ? 0 : depth[pre] + 1);
        par[v] = pre;
        updateEdgeType(pre, v, USED_DFS);
        for (auto&& nxt : G[v]) {
            if (nxt != pre) dfsTreeConstruct(nxt, v);
        }
    }
    void updateImos(int a, int b) {
        if (depth[a] < depth[b]) swap(a, b);

        if (par[a] != -1) {
            imosEdge[getEdge(a, par[a])]++;
        }
        if (par[b] != -1) {
            imosEdge[getEdge(b, par[b])]--;
        }
    }
    int imosFinal(int v, int pre) {
        int t = 0;
        for (auto&& nxt : G[v]) {
            if (nxt != pre && EdgeType[getEdge(nxt, v)] == USED_DFS) {
                t += imosFinal(nxt, v);
            }
        }
        if (pre != -1) imosEdge[getEdge(v, pre)] += t;
        return pre == -1 ? 0 : imosEdge[getEdge(v, pre)];
    }
    int extractCC(int v, int color) {
    	if (cmp[v] != -1) return 0;
    	cmp[v] = color;
    	int t = 1;
    	for (auto&& nxt : G[v]) {
    		if (EdgeType[getEdge(v, nxt)] != BRIDGE) {
    			t += extractCC(nxt, color);
    		}
    	}
    	return t;
    }
    void bicc() {
        dfsTreeConstruct(0, -1);
        for (auto&& p : EdgeType) {
            Edge e;
            int type;
            tie(e, type) = p;
            if (type == UNUSED) {
                updateImos(e.first, e.second);
            }
        }
        imosFinal(0, -1);
        for (auto&& p : EdgeType) {
            Edge e;
            int type;
            tie(e, type) = p;
            if (type == USED_DFS) {
                if (imosEdge[e] == 0) {
                    EdgeType[e] = BRIDGE;
                    bridges.emplace_back(e);
                }
            }
        }

		// rep(i, n) {
		// 	int size_cc = extractCC(i, num_cc);
		// 	if (size_cc > 0) {
		// 		size_of_vertex.emplace_back(size_cc);
		// 		num_cc++;
		// 	}
		// }
        //
        // r<set<int>> G_cc_st(num_cc);
		// for (auto&& p : EdgeType) {
        //     Edge e;
        //     int type;
        //     tie(e, type) = p;
        //     if (type == BRIDGE) {
		// 		G_cc_st[cmp[e.first]].insert(cmp[e.second]);
		// 		G_cc_st[cmp[e.second]].insert(cmp[e.first]);
        //     }
        // }
        //
		// rep(i, num_cc) {
		// 	G_cc.emplace_back(vector<int>(all(G_cc_st[i])));
		// }
    }
    vector<Edge> getBridges() {
        return bridges;
    }
};

signed main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);

    int V, E;
    cin >> V >> E;
    BICC bicc(V);
    rep(i, E) {
        int a, b;
        cin >> a >> b;
        bicc.addEdge(a, b);
    }

    bicc.bicc();
    auto bridges = bicc.getBridges();
    // printVP(bridges);
    for (auto&& e : bridges) {
        cout << e.first << " " << e.second << endl;
    }
}

Measured memory_bytes: 9100