#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Edge {
  int id;
  int from, to;
  int c;
};
bool operator<(const Edge& lhs, const Edge& rhs) { return lhs.c > rhs.c; };
using Graph = vector<vector<Edge>>;
class LCA {
  int N;
  const int logN = 20;
  vector<int> dep;
  vector<vector<int>> par;
  vector<vector<int>> v;
  void setDep(int v, const Graph& g) {
    for (auto e : g[v]) {
      dep[e.to] = dep[v] + 1;
      setDep(e.to, g);
    }
  }

 public:
  LCA(const Graph& g)
      : N(g.size()),
        dep(N),
        par(logN, vector<int>(N, -1)),
        v(logN, vector<int>(N, -1)) {
    setDep(0, g);
    par[0][0] = 0;
    for (int i = 0; i < N; i++) {
      for (auto e : g[i]) {
        par[0][e.to] = e.from;
        v[0][e.to] = e.c;
      }
    }
    for (int i = 1; i < logN; i++) {
      for (int j = 0; j < N; j++) {
        par[i][j] = par[i - 1][par[i - 1][j]];
        v[i][j] = max(v[i - 1][j], v[i - 1][par[i - 1][j]]);
      }
    }
  }
  int query(int a, int b) {
    if (dep[a] < dep[b]) {
      swap(a, b);
    }
    int res = -1;
    int d = dep[a] - dep[b];
    for (int i = logN - 1; i >= 0; i--) {
      if ((d >> i) & 1) {
        res = max(res, v[i][a]);
        a = par[i][a];
      }
    }
    if (a == b) {
      return res;
    }
    for (int i = logN - 1; i >= 0; i--) {
      if (par[i][a] != par[i][b]) {
        res = max(res, v[i][a]);
        res = max(res, v[i][b]);
        a = par[i][a];
        b = par[i][b];
      }
    }
    assert(a != b);
    res = max(res, v[0][a]);
    a = par[0][a];
    res = max(res, v[0][b]);
    b = par[0][b];
    assert(a == b);
    return res;
  }
};
void solve(int n, int m) {}
int main() {
  int n, m;
  cin >> n >> m;
  Graph g(n);
  vector<Edge> edges;
  for (int i = 0; i < m; i++) {
    int u, v, c;
    cin >> u >> v >> c;
    u--, v--;
    g[u].push_back(Edge{i, u, v, c});
    g[v].push_back(Edge{i, v, u, c});
    edges.push_back(Edge{i, u, v, c});
  }
  vector<int> flag(m, true);
  Graph tree(n);
  vector<int> used(n);
  {
    priority_queue<Edge> que;
    auto Push = [&](int v) {
      used[v] = true;
      for (auto& e : g[v]) {
        if (!used[e.to]) que.push(e);
      }
    };
    Push(0);
    while (!que.empty()) {
      auto e = que.top();
      que.pop();
      if (used[e.to]) continue;
      flag[e.id] = false;
      Push(e.to);
      tree[e.from].push_back(e);
    }
  }
  vector<pair<int, int>> ans;
  LCA lca(tree);
  auto calc = [&](Edge& e) { return lca.query(e.from, e.to); };
  for (auto& e : edges) {
    if (flag[e.id]) {
      ans.push_back({e.id, calc(e)});
    }
  }
  sort(ans.begin(), ans.end());
  assert(ans.size() == m - n + 1);
  for (ll i = 0; i < ans.size(); ++i) {
    cout << ans[i].second << endl;
  }
}
