2 0
 6 8
1 4 1
1 5 1
1 6 1
2 4 1
2 5 1
2 6 1
3 5 1
3 6 1
 6 12
1 3 8763000
1 4 8763000
1 5 8763000
1 6 8763000
2 3 8763000
2 4 1
2 5 8763000
2 6 1
3 5 8763000
3 6 8763000
4 5 8763000
4 6 2

0
 0
 8763002

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
struct DSU {
  int n;
  int par[N];
  int find(int x) {
    if (par[x] < 0)
      return x;
    else
      return par[x] = find(par[x]);
  }
  bool join(int x, int y) {
    x = find(x), y = find(y);
    if (x == y) return 0;
    if (par[x] > par[y]) swap(x, y);
    par[x] += par[y];
    par[y] = x;
    return 1;
  }
  void init(int _n) {
    n = _n;
    for (int i = 1; i <= n; i++) par[i] = -1;
  }
} overall, between;
int n, m;
set<int> avail;
set<int> adj[N];
vector<array<int, 3>> edges;
long long have;
void dfs(int u) {
  avail.erase(u);
  int v = 0;
  while (1) {
    auto it = avail.lower_bound(v);
    if (it == avail.end()) return;
    v = *it;
    if (!adj[u].count(v)) {
      overall.join(u, v);
      dfs(v);
      have--;
    }
    v++;
  }
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  have = (long long)n * (n - 1) / 2 - m;
  long long xorsum = 0;
  for (int i = (1); i <= (int)(n); i += (1)) avail.insert(i);
  for (int i = 0; i < (int)(m); i++) {
    int u, v, w;
    cin >> u >> v >> w;
    adj[u].insert(v);
    adj[v].insert(u);
    edges.push_back({w, u, v});
    xorsum ^= w;
  }
  overall.init(n), between.init(n);
  for (int i = (1); i <= (int)(n); i += (1))
    if (avail.count(i)) {
      dfs(i);
    }
  long long ans = 0, add = have > 0 ? 0 : xorsum;
  sort(edges.begin(), edges.end());
  for (auto& it : edges) {
    long long w = it[0], u = it[1], v = it[2];
    if (overall.join(u, v)) {
      ans += w;
      between.join(u, v);
    } else if (between.join(u, v)) {
      add = min(add, xorsum);
    }
  }
  cout << ans + add << '\n';
  return 0;
}
