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;
int n, m;
long long ans;
pair<int, pair<int, int> > e[200010];
set<int> g[200010];
int root[200010];
vector<int> vec[200010];
int findroot(int nod) {
  if (root[nod] != nod) root[nod] = findroot(root[nod]);
  return root[nod];
}
int main() {
  scanf("%d%d", &n, &m);
  int XOR = 0;
  for (int i = 1; i <= m; i++) {
    int x, y, z;
    scanf("%d%d%d", &x, &y, &z);
    e[i] = pair<int, pair<int, int> >(z, pair<int, int>(x, y));
    g[x].insert(y);
    g[y].insert(x);
    XOR ^= z;
  }
  sort(e + 1, e + m + 1);
  set<int> nodes;
  for (int i = 1; i <= n; i++)
    root[i] = i, vec[i].push_back(i), nodes.insert(i);
  for (int i = 1; i <= n; i++)
    if (nodes.count(i))
      for (auto it = nodes.begin(); it != nodes.end();)
        if (*it != i) {
          int r = findroot(*it);
          for (int x : vec[r]) {
            if (g[i].count(x)) continue;
            int a = findroot(i), b = r;
            if (vec[a].size() < vec[b].size()) swap(a, b);
            root[b] = a;
            vec[a].insert(vec[a].end(), vec[b].begin(), vec[b].end());
            nodes.erase(it++);
            goto CONT;
          }
          it++;
          continue;
        CONT:
          continue;
        } else
          it++;
  bool flag = n >= 1LL * n * (n - 1) / 2 - m + nodes.size();
  ans = flag ? XOR : 0;
  for (int i = 1; i <= m; i++) {
    int a = e[i].second.first, b = e[i].second.second, val = e[i].first;
    a = findroot(a);
    b = findroot(b);
    if (a == b) {
      if (flag && val < XOR) ans = ans - XOR + val, flag = false;
      continue;
    }
    root[b] = a;
    ans += val;
  }
  printf("%lld\n", ans);
  return 0;
}
