#include <bits/stdc++.h>
using namespace std;
struct RMQ {
  using type = int;
  static type id() { return 0; }
  static type op(const type& l, const type& r) { return max(l, r); }
};
template <typename M>
class segment_tree {
  using T = typename M::type;
  const int n;
  vector<T> data;
  int expand(int x) {
    int res;
    for (res = 1; res < x; res <<= 1)
      ;
    return res;
  }

 public:
  segment_tree(int n_) : n(expand(n_)), data(n * 2, M::id()) {}
  segment_tree(int n_, T val) : n(expand(n_)), data(n * 2, val) {}
  void init(const vector<T>& data_) {
    for (int i = 0; i < (int)data_.size(); i++) data[i + n] = data_[i];
    for (int i = n - 1; i >= 0; i--)
      data[i] = M::op(data[i * 2], data[i * 2 + 1]);
  }
  void update(int p, T val) {
    data[p += n] = val;
    while (p >>= 1) data[p] = M::op(data[p * 2], data[p * 2 + 1]);
  }
  T find(int l, int r) {
    l += n;
    r += n;
    T res1 = M::id(), res2 = M::id();
    while (l < r) {
      if (l & 1) res1 = M::op(res1, data[l++]);
      if (r & 1) res2 = M::op(data[--r], res2);
      l >>= 1;
      r >>= 1;
    }
    return M::op(res1, res2);
  }
};
class union_find {
  vector<int> par;

 public:
  union_find(int n) : par(n, -1) {}
  int find(int a) { return par[a] < 0 ? a : par[a] = find(par[a]); }
  bool same(int a, int b) { return find(a) == find(b); }
  void unite(int a, int b) {
    a = find(a);
    b = find(b);
    if (a == b) return;
    if (par[a] < par[b]) {
      par[a] += par[b];
      par[b] = a;
    } else {
      par[b] += par[a];
      par[a] = b;
    }
  }
  int size(int a) { return -par[find(a)]; }
};
class heavy_light_decomposition {
  const int n;
  vector<vector<int>> g;
  vector<int> par, head, in, out;
  void dfs1(int rt) {
    vector<int> size(n, 1);
    vector<size_t> iter(n);
    vector<pair<int, int>> stp;
    stp.reserve(n);
    stp.emplace_back(rt, -1);
    while (!stp.empty()) {
      int v = stp.back().first;
      if (iter[v] < g[v].size()) {
        if (g[v][iter[v]] != stp.back().second) {
          stp.emplace_back(g[v][iter[v]], v);
        }
        ++iter[v];
        continue;
      }
      par[v] = stp.back().second;
      for (auto& u : g[v])
        if (u == par[v]) {
          if (u != g[v].back()) swap(u, g[v].back());
          g[v].pop_back();
          break;
        }
      for (auto& u : g[v]) {
        size[v] += size[u];
        if (size[u] > size[g[v].front()]) swap(u, g[v].front());
      }
      stp.pop_back();
    }
  }
  void dfs2(int rt) {
    int it = 0;
    vector<size_t> iter(n);
    vector<int> st;
    st.reserve(n);
    st.push_back(rt);
    while (!st.empty()) {
      int v = st.back();
      if (!iter[v]) in[v] = it++;
      if (iter[v] < g[v].size()) {
        int u = g[v][iter[v]];
        head[u] = iter[v] ? u : head[v];
        st.push_back(u);
        ++iter[v];
        continue;
      }
      out[v] = it;
      st.pop_back();
    }
  }

 public:
  heavy_light_decomposition(int n_)
      : n(n_), g(n), par(n), head(n), in(n), out(n) {}
  heavy_light_decomposition(const vector<vector<int>>& G)
      : n(G.size()), g(G), par(n), head(n), in(n), out(n) {}
  void add_edge(int u, int v) {
    g[u].push_back(v);
    g[v].push_back(u);
  }
  void build(int rt = 0) {
    dfs1(rt);
    head[rt] = rt;
    dfs2(rt);
  }
  int get_id(int v) { return in[v]; }
  int get_lca(int u, int v) {
    while (true) {
      if (in[u] > in[v]) swap(u, v);
      if (head[u] == head[v]) return u;
      v = par[head[v]];
    }
  }
  void edge_path_query(int u, int v, function<void(int, int)> f) {
    while (true) {
      if (in[u] > in[v]) swap(u, v);
      if (head[u] != head[v]) {
        f(max(in[head[v]], in[u]), in[v] + 1);
        v = par[head[v]];
      } else {
        if (u != v) f(in[u] + 1, in[v] + 1);
        break;
      }
    }
  }
};
int main() {
  ios::sync_with_stdio(false), cin.tie(0);
  int n, m;
  cin >> n >> m;
  vector<tuple<int, int, int, int>> es;
  for (int i = 0; i < m; i++) {
    int u, v, c;
    cin >> u >> v >> c;
    --u, --v;
    es.emplace_back(c, u, v, i);
  }
  sort(es.begin(), es.end());
  heavy_light_decomposition hl(n);
  union_find uf(n);
  vector<int> used(m);
  vector<tuple<int, int, int>> vp;
  for (auto tp : es) {
    int u, v, c, id;
    tie(c, u, v, id) = tp;
    if (!uf.same(u, v)) {
      vp.emplace_back(u, v, c);
      uf.unite(u, v);
      hl.add_edge(u, v);
      used[id] = true;
    }
  }
  hl.build();
  segment_tree<RMQ> st(n);
  for (auto tp : vp) {
    int u, v, c;
    tie(u, v, c) = tp;
    hl.edge_path_query(u, v, [&](int l, int) { st.update(l, c); });
  }
  vector<int> res(m);
  for (auto tp : es) {
    int u, v, c, id;
    tie(c, u, v, id) = tp;
    if (!used[id]) {
      int val = 0;
      hl.edge_path_query(u, v,
                         [&](int l, int r) { val = max(val, st.find(l, r)); });
      res[id] = val;
    }
  }
  for (int i = 0; i < m; i++)
    if (!used[i]) {
      cout << res[i] << '\n';
    }
  return 0;
}
