#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#include <climits>
#include <cstring>
#include <cassert>

#define rep(i, m, n) for(int i=int(m);i<int(n);i++)
#define all(c) begin(c),end(c)

template<typename T1, typename T2>
inline void chmin(T1 &a, T2 b) { if (a > b) a = b; }

template<typename T1, typename T2>
inline void chmax(T1 &a, T2 b) { if (a < b) a = b; }

typedef long long int ll;
using ll = long long int;
using ull = long long unsigned int;
using Int = long long int;
using uInt = long long unsigned int;
using Double = long double;
using namespace std;
#define INF (1 << 30) - 1
#define INFl (ll)5e15
#define DEBUG 0
#define dump(x)  cerr << #x << " = " << (x) << endl
#define MOD 1000000007


//edit
struct edge {
    Int from, to, c;
};

class Lowlink {
    int N;
    vector<int> ord, low;

public:
    vector<int> articlulation;
    vector<pair<int, int>> bridge;
    vector<vector<int>> G;

    Lowlink(int N) : N(N) {
        ord.resize(N, -1);
        low.resize(N, -1);
        G.resize(N);
    };

    //　is_undirected : グラフが無向グラフかどうか
    void add_edge(int from, int to, bool is_undirected = true) {
        G[from].push_back(to);
        if (is_undirected) {
            G[to].push_back(from);
        }
    }


    void dfs(int v, int &k, int p = -1) {
        ord[v] = k++;
        low[v] = ord[v];

        bool is_articulation = false;
        int ct = 0; // dfs-tree 上の頂点vの子供の数

        for (auto to : G[v]) {
            if (ord[to] == -1) {
                ct++;
                dfs(to, k, v);
                chmin(low[v], low[to]);

                if (p == -1 && ord[v] <= low[to]) is_articulation = true;
                if (ord[v] < low[to]) bridge.emplace_back(v, to);
            }
            if (to != p) {
                chmin(low[v], ord[to]);
            }

        }

        if (p == -1 && ct > 1) is_articulation = true;
        if (is_articulation) articlulation.push_back(v);

    }

    // 頂点vを根とするdfs木を作成しつつ、lowlink等を求める
    void compute(int v = 0) {
        fill(ord.begin(), ord.end(), -1);
        fill(low.begin(), low.end(), -1);

        int k = 0;
        dfs(v, k);
    }

};

class Solve {

public:
    void solve() {
        Int N, M;
        cin >> N >> M;

        Lowlink lowlink(N);
        for (int i = 0; i < M; ++i) {
            int s, t;
            cin >> s >> t;
            lowlink.add_edge(s, t);
        }

        lowlink.compute();

        auto ans = lowlink.bridge;
        for (auto &e : ans) {
            if (e.first > e.second) {
                swap(e.first, e.second);
            }
        }

        sort(all(ans));

        for (auto e : ans) {
            cout << e.first << " " << e.second << endl;
        }


    }
};


int main() {
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
//    std::ifstream in("input.txt");
//    std::cin.rdbuf(in.rdbuf());

    Solve().solve();


    return 0;
}



Measured memory_bytes: 4416