#include <bits/stdc++.h>
using namespace std;
struct Node {
  int node, value;
  Node(int n, int v) {
    node = n;
    value = v;
  }
};
vector<Node> Graph[300000 + 1];
int parent[300000 + 1], depth[300000 + 1], heavy[300000 + 1], head[300000 + 1],
    position[300000 + 1], chain[300000 + 1];
long long int values[300000 + 1];
long long int Segment_Tree_Data[(300000 + 1) * 4];
void initialize(int N, int root) {
  int i;
  for (i = 1; i < 1 + N; i++) {
    while (Graph[i].size() > 0) {
      Graph[i].pop_back();
    }
    chain[i] = heavy[i] = position[i] = head[i] = parent[i] = depth[i] = 1 - 1;
  }
  depth[root] = 1;
}
long long int SegmentTreeDemand(long long int first, long long int second) {
  if (first > second)
    return first;
  else
    return second;
}
int DFSChainSetUp(int node) {
  int i, maximum_size = 0, Size = 1;
  for (i = 0; i < Graph[node].size(); i++) {
    if (Graph[node][i].node == parent[node]) continue;
    parent[Graph[node][i].node] = node;
    depth[Graph[node][i].node] = depth[node] + 1;
    int current_size = DFSChainSetUp(Graph[node][i].node);
    Size = Size + current_size;
    if (maximum_size < current_size) {
      maximum_size = current_size;
      heavy[node] = Graph[node][i].node;
    }
  }
  return Size;
}
int decompose(int node, int h, int pos) {
  head[node] = h;
  position[node] = pos++;
  chain[position[node]] = node;
  int i, current_position = pos;
  if (heavy[node] != 1 - 1)
    current_position = decompose(heavy[node], h, current_position);
  for (i = 0; i < Graph[node].size(); i++) {
    if (Graph[node][i].node == parent[node] ||
        Graph[node][i].node == heavy[node])
      continue;
    current_position =
        decompose(Graph[node][i].node, Graph[node][i].node, current_position);
  }
  return current_position;
}
void Segment_Tree_BuildUp(int index, int l, int r) {
  if (l == r) {
    Segment_Tree_Data[index] = values[chain[l]];
    return;
  }
  int middle = (l + r) / 2;
  Segment_Tree_BuildUp(index * 2, l, middle);
  Segment_Tree_BuildUp(index * 2 + 1, middle + 1, r);
  Segment_Tree_Data[index] = SegmentTreeDemand(
      Segment_Tree_Data[index * 2], Segment_Tree_Data[index * 2 + 1]);
}
long long int Segment_Tree_Query(int index, int l, int r, int L, int R) {
  if (R < l || L > r) return 0;
  if (l >= L && r <= R) return Segment_Tree_Data[index];
  if (l == r) {
    return Segment_Tree_Data[index];
  }
  int middle = (l + r) / 2;
  int lower = Segment_Tree_Query(index * 2, l, middle, L, R);
  int upper = Segment_Tree_Query(index * 2 + 1, middle + 1, r, L, R);
  return SegmentTreeDemand(lower, upper);
}
void DFSForSetUpValues(int node, int value) {
  values[node] = value;
  int i, index = -1;
  for (i = 0; i < Graph[node].size(); i++) {
    if (Graph[node][i].node == parent[node]) continue;
    DFSForSetUpValues(Graph[node][i].node, Graph[node][i].value);
  }
}
void BuildUpFullChain(int N, int root) {
  int i, temp = DFSChainSetUp(root);
  temp = decompose(1, 1, 1);
  DFSForSetUpValues(1, 0);
  Segment_Tree_BuildUp(1, 1, 1 + N - 1);
}
long long int Query(int first, int second, int root, int N) {
  int i, j;
  long long int now, result = 0;
  for (; head[first] != head[second]; second = parent[head[second]]) {
    if (depth[head[first]] > depth[head[second]]) {
      i = first;
      first = second;
      second = i;
    }
    now = Segment_Tree_Query(1, 1, 1 + N - 1, position[head[second]],
                             position[second]);
    result = SegmentTreeDemand(result, now);
  }
  if (depth[first] != depth[second]) {
    if (depth[first] > depth[second]) {
      i = first;
      first = second;
      second = i;
    }
    now = Segment_Tree_Query(1, 1, 1 + N - 1, position[first] + 1,
                             position[second]);
    result = SegmentTreeDemand(result, now);
  }
  return result;
}
struct Edge {
  int u, v, value, idx;
  Edge(int a, int b, int val, int p) {
    u = a;
    v = b;
    value = val;
    idx = p;
  }
};
vector<Edge> Queries;
vector<Edge> List;
vector<int> Indices;
int P[300000 + 1];
bool cmppp(Edge a, Edge b) { return a.idx < b.idx; }
int Union(int x) {
  if (P[x] == x)
    return x;
  else {
    P[x] = Union(P[x]);
    return P[x];
  }
}
bool comp(int a, int b) { return List[a].value < List[b].value; }
int main() {
  int N, M, i;
  scanf("%d %d", &N, &M);
  initialize(N, 1);
  for (i = 1; i < 1 + N; i++) {
    P[i] = i;
  }
  for (i = 0; i < M; i++) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    List.push_back(Edge(u, v, w, i));
    Indices.push_back(i);
  }
  sort(Indices.begin(), Indices.end(), comp);
  for (i = 0; i < Indices.size(); i++) {
    int f = List[Indices[i]].u;
    int s = List[Indices[i]].v;
    int a = Union(f);
    int b = Union(s);
    if (a == b) {
      Queries.push_back(List[Indices[i]]);
    } else {
      Graph[f].push_back(Node(s, List[Indices[i]].value));
      Graph[s].push_back(Node(f, List[Indices[i]].value));
      P[b] = P[a];
    }
  }
  BuildUpFullChain(N, 1);
  sort(Queries.begin(), Queries.end(), cmppp);
  for (i = 0; i < Queries.size(); i++) {
    printf("%I64d\n", Query(Queries[i].u, Queries[i].v, 1, N));
  }
  return 0;
}
