#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>

#include <algorithm>
#include <bitset>
#include <complex>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

#include <cassert>
#include <functional>

typedef long long ll;
using namespace std;

#ifndef LOCAL
#define debug(...) ;
#else
#define debug(...) cerr << __LINE__ << " : " << #__VA_ARGS__ << " = " << _tostr(__VA_ARGS__) << endl;

template<typename T>
ostream &operator<<(ostream &out, const vector<T> &v);

template<typename T1, typename T2>
ostream &operator<<(ostream &out, const pair<T1, T2> &p) {
  out << "{" << p.first << ", " << p.second << "}";
  return out;
}

template<typename T>
ostream &operator<<(ostream &out, const vector<T> &v) {
  out << '{';
  for (const T &item : v) out << item << ", ";
  out << "\b\b}";
  return out;
}

void _tostr_rec(ostringstream &oss) {
  oss << "\b\b \b";
}

template<typename Head, typename... Tail>
void _tostr_rec(ostringstream &oss, Head &&head, Tail &&... tail) {
  oss << head << ", ";
  _tostr_rec(oss, forward<Tail>(tail)...);
}

template<typename... T>
string _tostr(T &&... args) {
  ostringstream oss;
  int size = sizeof...(args);
  if (size > 1) oss << "{";
  _tostr_rec(oss, forward<T>(args)...);
  if (size > 1) oss << "}";
  return oss.str();
}
#endif

#define mod 1000000007 //1e9+7(prime number)
#define INF 1000000000 //1e9
#define LLINF 2000000000000000000LL //2e18
#define SIZE 200010

/* Bridges & 2-edge-connected Components */

struct Bridges {
  vector<pair<int, int>> edges;
  vector<vector<pair<int, int>>> G;

  vector<int> cmp, isBridge; //圧縮後に属するComponent番号, 橋であるか
  vector<pair<int, int>> cmpEdges; //圧縮後のedge

  int idx, cmpIdx;
  vector<int> ord, inSt;
  stack<int> roots, st;

  Bridges(int N): G(N, vector<pair<int, int>>()), cmp(N), idx(0), cmpIdx(0), ord(N, -1), inSt(N, 0) {}

  void add_edge(int u, int v) {
    G[u].push_back({v, edges.size()});
    G[v].push_back({u, edges.size()});
    edges.push_back({u, v});
    isBridge.push_back(false);
  }

  void dfs(int now, int eid = -1) {
    ord[now] = idx++;
    roots.push(now);
    st.push(now);
    inSt[now] = true;

    for (auto e : G[now]) {
      int to = e.first;
      if (ord[to] == -1)
        dfs(to, e.second);
      else if (eid != e.second && inSt[to])
        while (ord[roots.top()] > ord[to]) roots.pop();
    }
    if (now == roots.top()) {
      while (1) {
        int w = st.top();
        st.pop();
        inSt[w] = false;
        cmp[w] = cmpIdx;
        if (now == w) break;
      }
      if (eid != -1) isBridge[eid] = true;
      roots.pop();
      cmpIdx++;
    }
  }

  void build() {
    for (int i = 0; i < (int)ord.size(); i++)
      if (ord[i] == -1)
        dfs(i);

    for (int i = 0; i < (int)edges.size(); i++) {
      if (isBridge[i])
        cmpEdges.push_back({cmp[edges[i].first], cmp[edges[i].second]});
    }
  }
};

int main() {
  int V, E;

  scanf("%d%d", &V, &E);

  Bridges bridges(V);

  for (int i = 0; i < E; i++) {
    int s, t;
    scanf("%d%d", &s, &t);
    bridges.add_edge(min(s, t), max(s, t));
  }

  bridges.build();

  vector<pair<int, int>> ans;

  debug(bridges.isBridge, E);

  for (int i = 0; i < E; i++) {
    if (bridges.isBridge[i])
      ans.push_back(bridges.edges[i]);
  }

  sort(ans.begin(), ans.end());

  for (auto p : ans) {
    printf("%d %d\n", p.first, p.second);
  }
}



Measured memory_bytes: 5640