#include <bits/stdc++.h>
using namespace std;
const int MAX = 2e5 + 9;
class LazySegmentTree {
 public:
  void reset(int sz, bool clr = false) {
    n = sz;
    treeMn.assign(n << 2, INT_MAX);
    treeMx.assign(n << 2, INT_MAX);
    lazyAssign.assign(n << 2, -1);
  }
  void minimize(int L, int R, int value) { minimize(1, n, 1, L, R, value); }
  int getMax(int L, int R) { return getMax(1, n, 1, L, R); }

 private:
  void push(int low, int high, int pos) {
    if (lazyAssign[pos] != -1) {
      treeMn[pos] = treeMx[pos] = lazyAssign[pos];
      if (low != high) {
        lazyAssign[pos << 1] = lazyAssign[pos << 1 | 1] = lazyAssign[pos];
      }
      lazyAssign[pos] = -1;
    }
  }
  void minimize(int low, int high, int pos, int L, int R, int value) {
    push(low, high, pos);
    if (L > high || R < low || treeMx[pos] <= value) {
      return;
    }
    if (L <= low && R >= high && treeMn[pos] >= value) {
      lazyAssign[pos] = value;
      push(low, high, pos);
      return;
    }
    int mid = (low + high) >> 1;
    minimize(low, mid, pos << 1, L, R, value);
    minimize(mid + 1, high, pos << 1 | 1, L, R, value);
    treeMn[pos] = min(treeMn[pos << 1], treeMn[pos << 1 | 1]);
    treeMx[pos] = max(treeMx[pos << 1], treeMx[pos << 1 | 1]);
  }
  int getMax(int low, int high, int pos, int L, int R) {
    push(low, high, pos);
    if (L > high || R < low) {
      return 0;
    }
    if (L <= low && R >= high) {
      return treeMx[pos];
    }
    int mid = (low + high) >> 1;
    return max(getMax(low, mid, pos << 1, L, R),
               getMax(mid + 1, high, pos << 1 | 1, L, R));
  }
  int n;
  vector<int> treeMx;
  vector<int> treeMn;
  vector<int> lazyAssign;
};
class Hld {
 public:
  void build(int n, const vector<vector<pair<int, int> > >& adj) {
    dfsCnt = 0;
    tree1.reset(n);
    tree2.reset(n);
    head.resize(n + 1);
    heavy.resize(n + 1);
    pos.resize(n + 1);
    subtreeSize.resize(n + 1);
    parent.resize(n + 1);
    depth.resize(n + 1);
    dfs(1, adj);
    decompose(1, 1, INT_MAX, adj);
  }
  void minimizePath(int x, int y, int value) {
    for (; head[x] != head[y]; y = parent[head[y]]) {
      if (depth[head[x]] > depth[head[y]]) {
        swap(x, y);
      }
      tree2.minimize(pos[head[y]], pos[y], value);
    }
    if (depth[x] > depth[y]) {
      swap(x, y);
    }
    if (x != y) {
      tree2.minimize(pos[x] + 1, pos[y], value);
    }
  }
  int getEdgeValue(int x, int y) {
    int position = max(pos[x], pos[y]);
    return tree2.getMax(position, position);
  }
  int getMaxOnPath(int x, int y) {
    int value = 0;
    for (; head[x] != head[y]; y = parent[head[y]]) {
      if (depth[head[x]] > depth[head[y]]) {
        swap(x, y);
      }
      value = max(value, tree1.getMax(pos[head[y]], pos[y]));
    }
    if (depth[x] > depth[y]) {
      swap(x, y);
    }
    if (x != y) {
      value = max(value, tree1.getMax(pos[x] + 1, pos[y]));
    }
    return value;
  }

 private:
  void dfs(int node, const vector<vector<pair<int, int> > >& adj) {
    int maxSubtreeSize = 0;
    subtreeSize[node] = 1;
    heavy[node].first = 0;
    for (const pair<int, int>& p : adj[node]) {
      int child = p.first;
      int cost = p.second;
      if (child != parent[node]) {
        parent[child] = node;
        depth[child] = depth[node] + 1;
        dfs(child, adj);
        subtreeSize[node] += subtreeSize[child];
        if (subtreeSize[child] > maxSubtreeSize) {
          maxSubtreeSize = subtreeSize[child];
          heavy[node] = {child, cost};
        }
      }
    }
  }
  void decompose(int node, int chainRoot, int edge,
                 const vector<vector<pair<int, int> > >& adj) {
    head[node] = chainRoot;
    pos[node] = ++dfsCnt;
    tree1.minimize(pos[node], pos[node], edge);
    if (heavy[node].first) {
      decompose(heavy[node].first, chainRoot, heavy[node].second, adj);
    }
    for (const pair<int, int>& p : adj[node]) {
      int child = p.first;
      int cost = p.second;
      if (child != parent[node] && child != heavy[node].first) {
        decompose(child, child, cost, adj);
      }
    }
  }
  int dfsCnt;
  vector<int> head;
  vector<pair<int, int> > heavy;
  vector<int> pos;
  vector<int> subtreeSize;
  vector<int> parent;
  vector<int> depth;
  LazySegmentTree tree1;
  LazySegmentTree tree2;
};
void Kruskal(int n, vector<vector<pair<int, int> > >& adj,
             vector<pair<pair<int, int>, pair<int, int> > >& edges,
             vector<bool>& isInMst) {
  vector<int> parent(n + 1);
  vector<int> r(n + 1);
  for (int i = 1; i <= n; ++i) {
    parent[i] = i;
  }
  function<int(int)> findSet = [&parent, &findSet](int node) -> int {
    if (parent[node] == node) {
      return node;
    } else {
      return parent[node] = findSet(parent[node]);
    }
  };
  auto mergeSets = [&findSet, &parent, &r](int x, int y) {
    int firstParent = findSet(x);
    int secondParent = findSet(y);
    assert(firstParent != secondParent);
    if (r[firstParent] > r[secondParent]) {
      swap(firstParent, secondParent);
    } else if (r[firstParent] == r[secondParent]) {
      ++r[secondParent];
    }
    parent[firstParent] = secondParent;
  };
  vector<pair<pair<int, int>, pair<int, int> > > tempEdges(edges);
  sort(tempEdges.begin(), tempEdges.end());
  for (int i = 0; i < tempEdges.size(); ++i) {
    int x = tempEdges[i].second.first;
    int y = tempEdges[i].second.second;
    int w = tempEdges[i].first.first;
    int idx = tempEdges[i].first.second;
    if (findSet(x) != findSet(y)) {
      adj[x].push_back({y, w});
      adj[y].push_back({x, w});
      isInMst[idx] = true;
      mergeSets(x, y);
    }
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int n, m;
  cin >> n >> m;
  vector<pair<pair<int, int>, pair<int, int> > > edges(m);
  for (int i = 0; i < m; ++i) {
    int x, y, w;
    cin >> x >> y >> w;
    edges[i] = {{w, i}, {x, y}};
  }
  vector<vector<pair<int, int> > > adj(n + 1);
  vector<bool> isInMst(m);
  Kruskal(n, adj, edges, isInMst);
  Hld hld;
  hld.build(n, adj);
  vector<int> answer(m, INT_MAX);
  for (int i = 0; i < m; ++i) {
    if (!isInMst[i]) {
      int x = edges[i].second.first;
      int y = edges[i].second.second;
      int w = edges[i].first.first;
      answer[i] = hld.getMaxOnPath(x, y) - 1;
      hld.minimizePath(x, y, w - 1);
    }
  }
  for (int i = 0; i < m; ++i) {
    if (isInMst[i]) {
      int x = edges[i].second.first;
      int y = edges[i].second.second;
      answer[i] = hld.getEdgeValue(x, y);
      if (answer[i] == INT_MAX) {
        answer[i] = -1;
      }
    }
  }
  for (int i = 0; i < m; ++i) {
    cout << answer[i] << " ";
  }
  return 0;
}
