#include <bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx")
#pragma GCC optimize("unroll-loops")
using namespace std;
template <typename T1, typename T2>
inline void chkmin(T1 &first, T2 second) {
  if (first > second) first = second;
}
template <typename T1, typename T2>
inline void chkmax(T1 &first, T2 second) {
  if (first < second) first = second;
}
template <typename T, typename U>
inline ostream &operator<<(ostream &_out, const pair<T, U> &_p) {
  _out << _p.first << ' ' << _p.second;
  return _out;
}
template <typename T, typename U>
inline istream &operator>>(istream &_in, pair<T, U> &_p) {
  _in >> _p.first >> _p.second;
  return _in;
}
template <typename T>
inline ostream &operator<<(ostream &_out, const vector<T> &_v) {
  if (_v.empty()) {
    return _out;
  }
  _out << _v.front();
  for (auto _it = ++_v.begin(); _it != _v.end(); ++_it) {
    _out << ' ' << *_it;
  }
  return _out;
}
template <typename T>
inline istream &operator>>(istream &_in, vector<T> &_v) {
  for (auto &_i : _v) {
    _in >> _i;
  }
  return _in;
}
template <typename T>
inline ostream &operator<<(ostream &_out, const set<T> &_s) {
  if (_s.empty()) {
    return _out;
  }
  _out << *_s.begin();
  for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) {
    _out << ' ' << *_it;
  }
  return _out;
}
template <typename T>
inline ostream &operator<<(ostream &_out, const multiset<T> &_s) {
  if (_s.empty()) {
    return _out;
  }
  _out << *_s.begin();
  for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) {
    _out << ' ' << *_it;
  }
  return _out;
}
template <typename T>
inline ostream &operator<<(ostream &_out, const unordered_set<T> &_s) {
  if (_s.empty()) {
    return _out;
  }
  _out << *_s.begin();
  for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) {
    _out << ' ' << *_it;
  }
  return _out;
}
template <typename T>
inline ostream &operator<<(ostream &_out, const unordered_multiset<T> &_s) {
  if (_s.empty()) {
    return _out;
  }
  _out << *_s.begin();
  for (auto _it = ++_s.begin(); _it != _s.end(); ++_it) {
    _out << ' ' << *_it;
  }
  return _out;
}
template <typename T, typename U>
inline ostream &operator<<(ostream &_out, const map<T, U> &_m) {
  if (_m.empty()) {
    return _out;
  }
  _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')';
  for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) {
    _out << ", (" << _it->first << ": " << _it->second << ')';
  }
  return _out;
}
template <typename T, typename U>
inline ostream &operator<<(ostream &_out, const unordered_map<T, U> &_m) {
  if (_m.empty()) {
    return _out;
  }
  _out << '(' << _m.begin()->first << ": " << _m.begin()->second << ')';
  for (auto _it = ++_m.begin(); _it != _m.end(); ++_it) {
    _out << ", (" << _it->first << ": " << _it->second << ')';
  }
  return _out;
}
const int N = 2e5 + 5;
int n, m;
int dsu[N];
vector<pair<int, int>> edge[N];
vector<pair<int, pair<int, int>>> edges;
int get(int i) { return i == dsu[i] ? i : dsu[i] = get(dsu[i]); }
bool merge(int i, int j) {
  i = get(i);
  j = get(j);
  if (i == j) return false;
  dsu[i] = j;
  return true;
}
void dfs(int i, int t, int p = -1, int maxe = 0) {
  if (i == t) {
    cout << maxe << '\n';
    exit(0);
  }
  for (auto e : edge[i]) {
    if (e.first == p) continue;
    dfs(e.first, t, i, max(maxe, e.second));
  }
}
int main() {
  ios::sync_with_stdio(0);
  srand(time(0));
  cin >> n >> m;
  edges.resize(m);
  for (int i = 0; i < m; ++i) {
    cin >> edges[i].second.first >> edges[i].second.second >> edges[i].first;
  }
  auto v = edges[0];
  sort(edges.begin(), edges.end());
  bool was = false;
  for (int i = 0; i <= n; ++i) dsu[i] = i;
  for (auto i : edges) {
    if (v == i) {
      if (!was) {
        was = true;
        continue;
      }
    }
    if (merge(i.second.first, i.second.second)) {
      edge[i.second.first].push_back({i.second.second, i.first});
      edge[i.second.second].push_back({i.second.first, i.first});
    }
  }
  dfs(v.second.first, v.second.second);
  cout << 1000000000 << '\n';
}
