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;
struct Arete {
  long long u, v, w;
  Arete(long long _u, long long _v, long long _w) : u(_u), v(_v), w(_w) {}
  Arete() {}
  bool operator<(Arete other) const { return w < other.w; }
};
const long long MAXN = 2e5;
vector<long long> adj[MAXN];
vector<Arete> aretes;
long long nbSommets, nbAretes;
set<long long> sommetsRestants;
long long nbCC;
vector<pair<long long, long long>> aretesNulles;
struct UnionFind {
  vector<long long> id;
  vector<bool> containsNull;
  UnionFind() {}
  UnionFind(long long N) {
    id.assign(N, -1);
    containsNull.assign(N, false);
  }
  long long find(long long u) {
    if (id[u] < 0) return u;
    return id[u] = find(id[u]);
  }
  bool merge(long long u, long long v) {
    u = find(u), v = find(v);
    if (u == v) return false;
    if (id[u] > id[v]) swap(u, v);
    id[u] += id[v];
    containsNull[u] = containsNull[u] or containsNull[v];
    id[v] = u;
    return true;
  }
};
UnionFind uf(MAXN);
void dfs(long long iNoeud) {
  sommetsRestants.erase(iNoeud);
  long long deg = adj[iNoeud].size();
  for (long long iArete(0); iArete <= deg; ++iArete) {
    while (!sommetsRestants.empty()) {
      auto it =
          sommetsRestants.upper_bound(iArete ? adj[iNoeud][iArete - 1] : -1);
      if (it == sommetsRestants.end() or
          (iArete < deg and *it >= adj[iNoeud][iArete]))
        break;
      if (uf.merge(iNoeud, *it)) aretesNulles.emplace_back(iNoeud, *it);
      dfs(*it);
    }
  }
}
signed main(void) {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  cout.tie(0);
  cin >> nbSommets >> nbAretes;
  aretes.resize(nbAretes);
  long long valXor = 0;
  for (long long iArete(0); iArete < nbAretes; ++iArete) {
    long long u, v, w;
    cin >> u >> v >> w;
    valXor ^= w;
    --u, --v;
    aretes[iArete] = Arete(u, v, w);
    adj[u].push_back(v);
    adj[v].push_back(u);
  }
  sort(aretes.begin(), aretes.end());
  nbCC = 0;
  for (long long i(0); i < nbSommets; ++i) sommetsRestants.insert(i);
  for (long long i(0); i < nbSommets; ++i)
    if (sommetsRestants.count(i)) {
      ++nbCC;
      dfs(i);
    }
  for (long long iSommet(0); iSommet < nbSommets; ++iSommet)
    if (uf.find(iSommet) != iSommet) uf.containsNull[uf.find(iSommet)] = true;
  long long nbLibres = (nbSommets * (nbSommets - 1)) / 2 - nbAretes;
  long long nbAretesPrises = aretesNulles.size();
  long long sol = 2e18;
  long long curCost(nbAretesPrises == nbLibres ? valXor : 0);
  bool xorRemoved = nbAretesPrises < nbLibres;
  if (nbCC == 1) sol = curCost;
  for (auto [u, v, w] : aretes) {
    if (uf.merge(u, v))
      nbCC--, curCost += w;
    else if (!xorRemoved and w < valXor and uf.containsNull[uf.find(u)]) {
      curCost += w - valXor;
      xorRemoved = true;
    }
    if (nbCC == 1) sol = min(sol, curCost);
  }
  assert(nbCC == 1);
  cout << sol << endl;
}
