#include<iostream>
#include<queue>
#include<cstring>
#include<algorithm>
#define RED 0
#define BLACK 1
const int maxn = 2e5;
using namespace std;
int n, m;
struct Edge {
int next;
int to;
int val;
}edge[maxn];
int head[maxn], tot = 0;
void add(int u, int v, int w) {
edge[++tot].val = w;
edge[tot].to = v;
edge[tot].next = head[u];
head[u] = tot;
}
queue<int>q;
bool vis[maxn], color[maxn];
bool bfs(int x,int mid) {
q.push(x);
color[x] = RED;
vis[x] = 1;
while (!q.empty()) {
int u = q.front();
q.pop();
for (int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (edge[i].val >= mid) {
if (!vis[v]) {
color[v] = 1 - color[u];
q.push(v);
vis[v] = 1;
}
else if (vis[v] && color[v] == color[u])
return false;
else
continue;
}
}
}
return true;
}
bool solve(int mid) {
for (int i = 1; i <= n; ++i) {
if (vis[i])
continue;
else if (bfs(i, mid))
continue;
else
return false;
}
return true;
}
int main() {
cin >> n >> m;
int maxW = 0;
for (int i = 1; i <= m; ++i) {
int u, v, w;
cin >> u >> v >> w;
add(u, v, w);
add(v, u, w);
maxW = max(maxW, w);
}
int L = 0, R = maxW + 1;
while (R > L + 1) {
int mid = (L + R) >> 1;
if (solve(mid))
R = mid;
else
L = mid;
memset(color, 0, sizeof(color));
memset(vis, 0, sizeof(vis));
while (!q.empty())
q.pop();
}
cout << L << endl;
return 0;
}