#include <bits/stdc++.h>
using namespace std;
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  long long n, m;
  cin >> n >> m;
  vector<long long> dsu_parents((size_t)n), dsu_sizes((size_t)n, (long long)1);
  iota(dsu_parents.begin(), dsu_parents.end(), (long long)0);
  function<long long(long long)> dsu_query = [&](long long x) {
    return dsu_parents[x] == x ? x
                               : (dsu_parents[x] = dsu_query(dsu_parents[x]));
  };
  function<void(long long, long long)> dsu_join = [&](long long x,
                                                      long long y) {
    x = dsu_query(x), y = dsu_query(y);
    if (x != y) {
      if (dsu_sizes[y] > dsu_sizes[x]) {
        swap(x, y);
      }
      dsu_parents[y] = x;
      dsu_sizes[x] += dsu_sizes[y];
    }
  };
  vector<tuple<long long, long long, long long>> edges((size_t)m);
  vector<pair<long long, long long>> all_edges;
  vector<vector<long long>> all_adj((size_t)n);
  for (long long i = 0; i < m; i++) {
    cin >> get<1>(edges[i]) >> get<2>(edges[i]) >> get<0>(edges[i]);
    get<1>(edges[i])--, get<2>(edges[i])--;
    all_edges.emplace_back(get<1>(edges[i]), get<2>(edges[i]));
    all_adj[get<1>(edges[i])].push_back(get<2>(edges[i]));
    all_adj[get<2>(edges[i])].push_back(get<1>(edges[i]));
  }
  vector<map<long long, long long>> adj((size_t)n);
  sort(edges.begin(), edges.end());
  for (auto [w, u, v] : edges) {
    if (dsu_query(u) != dsu_query(v)) {
      dsu_join(u, v);
      adj[u][v] = w;
      adj[v][u] = w;
    }
  }
  vector<long long> parents((size_t)n, -1), depths((size_t)n, 0),
      sizes((size_t)n, 1), heavy_children((size_t)n, -1), heads((size_t)n, -1),
      times((size_t)n, -1);
  long long current_time = 0;
  long long sparse_table_size = 22;
  vector<vector<long long>> sparse_table((size_t)sparse_table_size,
                                         vector<long long>((size_t)n, 0));
  function<void(long long)> visit_initial = [&](long long u) {
    for (pair<long long, long long> p : adj[u]) {
      long long v = p.first;
      if (v != parents[u]) {
        parents[v] = u;
        visit_initial(v);
        sizes[u] += sizes[v];
        if (heavy_children[u] == -1 || sizes[v] > sizes[heavy_children[u]]) {
          heavy_children[u] = v;
        }
      }
    }
  };
  function<void(long long)> visit_decompose = [&](long long u) {
    heads[u] = parents[u] == -1 || heavy_children[parents[u]] != u
                   ? u
                   : heads[parents[u]];
    times[u] = current_time++;
    if (heavy_children[u] != -1) {
      depths[heavy_children[u]] = depths[u];
      visit_decompose(heavy_children[u]);
    }
    for (auto [v, w] : adj[u]) {
      if (v != parents[u]) {
        if (v != heavy_children[u]) {
          depths[v] = depths[u] + 1;
          visit_decompose(v);
        }
        sparse_table[0][times[v]] = w;
      }
    }
  };
  visit_initial(0);
  visit_decompose(0);
  for (long long i = 1; i < sparse_table_size; i++) {
    for (long long j = 0; j + (1 << (i - 1)) < n; j++) {
      sparse_table[i][j] =
          max(sparse_table[i - 1][j], sparse_table[i - 1][j + (1 << (i - 1))]);
    }
  }
  auto sparse_table_query = [&](long long x, long long y) {
    if (x > y) {
      return (long long)0;
    }
    long long z = (long long)log2(y - x + 1);
    return max(sparse_table[z][x], sparse_table[z][y - (1 << z) + 1]);
  };
  auto query = [&](long long x, long long y) {
    long long z = 0;
    while (heads[x] != heads[y] && depths[x] > depths[y]) {
      z = max(z, sparse_table_query(times[heads[x]], times[x]));
      x = parents[heads[x]];
    }
    while (heads[x] != heads[y] && depths[y] > depths[x]) {
      z = max(z, sparse_table_query(times[heads[y]], times[y]));
      y = parents[heads[y]];
    }
    while (x != -1 && y != -1 && heads[x] != heads[y]) {
      z = max(z, sparse_table_query(times[heads[x]], times[x]));
      x = parents[heads[x]];
      z = max(z, sparse_table_query(times[heads[y]], times[y]));
      y = parents[heads[y]];
    }
    if (x != -1 && y != -1) {
      z = max(z, sparse_table_query(min(times[x], times[y]) + 1,
                                    max(times[x], times[y])));
    }
    return z;
  };
  long long tree_size = 1 << 22;
  vector<long long> tree((size_t)tree_size, (long long)1e9);
  function<void(long long, long long, long long, long long, long long,
                long long)>
      tree_update = [&](long long tree_v, long long tree_l, long long tree_r,
                        long long l, long long r, long long x) {
        if (tree_l >= l && tree_r <= r) {
          tree[tree_v] = min(tree[tree_v], x);
        } else if (tree_l <= r && tree_r >= l) {
          tree_update(tree_v * 2 + 0, tree_l, tree_l + (tree_r - tree_l) / 2, l,
                      r, x);
          tree_update(tree_v * 2 + 1, tree_r - (tree_r - tree_l) / 2, tree_r, l,
                      r, x);
        }
      };
  function<long long(long long, long long, long long, long long)> tree_query =
      [&](long long tree_v, long long tree_l, long long tree_r, long long x) {
        if (tree_l == tree_r) {
          return tree[tree_v];
        } else {
          if (x <= tree_l + (tree_r - tree_l) / 2) {
            return min(tree[tree_v],
                       tree_query(tree_v * 2 + 0, tree_l,
                                  tree_l + (tree_r - tree_l) / 2, x));
          } else {
            return min(tree[tree_v],
                       tree_query(tree_v * 2 + 1,
                                  tree_r - (tree_r - tree_l) / 2, tree_r, x));
          }
        }
      };
  auto update = [&](long long x, long long y, long long z) {
    while (heads[x] != heads[y] && depths[x] > depths[y]) {
      tree_update(1, 0, tree_size / 2 - 1, times[heads[x]], times[x], z);
      x = parents[heads[x]];
    }
    while (heads[x] != heads[y] && depths[y] > depths[x]) {
      tree_update(1, 0, tree_size / 2 - 1, times[heads[y]], times[y], z);
      y = parents[heads[y]];
    }
    while (x != -1 && y != -1 && heads[x] != heads[y]) {
      tree_update(1, 0, tree_size / 2 - 1, times[heads[x]], times[x], z);
      x = parents[heads[x]];
      tree_update(1, 0, tree_size / 2 - 1, times[heads[y]], times[y], z);
      y = parents[heads[y]];
    }
    if (x != -1 && y != -1) {
      tree_update(1, 0, tree_size / 2 - 1, min(times[x], times[y]) + 1,
                  max(times[x], times[y]), z);
    }
  };
  for (auto [w, u, v] : edges) {
    if (adj[u].find(v) == adj[u].end()) {
      update(u, v, w);
    }
  }
  for (auto [u, v] : all_edges) {
    if (adj[u].find(v) != adj[u].end()) {
      cout << tree_query(1, 0, tree_size / 2 - 1, max(times[u], times[v]))
           << "\n";
    } else {
      cout << query(u, v) << "\n";
    }
  }
  return 0;
}
