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 MAXN = 202020;
set<int> G[MAXN], bad;
int dsu[MAXN];
int fnd(int x) { return x == dsu[x] ? x : dsu[x] = fnd(dsu[x]); }
void merg(int x, int y) {
  x = fnd(x), y = fnd(y);
  if (x != y) dsu[x] = y;
}
vector<tuple<int, int, int> > edges;
int n, m;
void bfs(int x) {
  queue<int> q;
  q.push(x);
  bad.erase(x);
  while (!q.empty()) {
    int f = q.front();
    q.pop();
    for (auto it = bad.begin(); it != bad.end();) {
      int g = *it;
      if (G[g].find(f) == G[g].end()) {
        merg(x, g);
        auto nxt = it;
        ++nxt;
        q.push(g);
        bad.erase(it);
        it = nxt;
      } else
        it++;
    }
  }
}
int main() {
  scanf("%d%d", &n, &m);
  long long edgecnt = 1LL * n * (n - 1) / 2 - m, tredge = n;
  int ws = 0;
  for (int i = 1; i <= n; ++i) dsu[i] = i, bad.insert(i);
  for (int i = 1; i <= m; ++i) {
    static int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    edges.emplace_back(w, u, v);
    G[u].insert(v);
    G[v].insert(u);
    ws ^= w;
  }
  for (int i = 1; i <= n; ++i)
    if (bad.count(i)) bfs(i), tredge--;
  long long tot = 0, pl = (edgecnt == 0 || edgecnt > tredge) ? 0 : ws;
  for (auto [w, u, v] : edges)
    if (fnd(u) == fnd(v) && w < pl) pl = w;
  sort(edges.begin(), edges.end());
  for (auto [w, u, v] : edges) {
    int fu = fnd(u), fv = fnd(v);
    if (fu != fv) {
      dsu[fu] = fv;
      tot += w;
    }
  }
  printf("%lld\n", tot + pl);
  return 0;
}
