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;
vector<int> g[200010];
vector<pair<int, pair<int, int>>> arestas;
int parent[200010], ori[200010], tam[200010], n;
set<int> disponiveis;
int Find(int x) {
  if (x == parent[x]) return x;
  parent[x] = Find(parent[x]);
  return parent[x];
}
bool Union(int a, int b) {
  int x = Find(a);
  int y = Find(b);
  if (x == y) return false;
  if (tam[x] > tam[y]) swap(x, y);
  parent[x] = y;
  tam[y] += tam[x];
  return true;
}
void dfs(int node) {
  disponiveis.erase(node);
  sort(g[node].begin(), g[node].end());
  int v = 0;
  while (v < n) {
    auto it = disponiveis.lower_bound(v);
    if (it == disponiveis.end()) return;
    v = *it;
    if (!binary_search(g[node].begin(), g[node].end(), v)) {
      Union(node, v);
      dfs(v);
    }
    v++;
  }
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  int m;
  cin >> n >> m;
  for (int i = 0; i < n; i++) {
    parent[i] = i;
    disponiveis.insert(i);
  }
  int Xor = 0;
  long long cont = 1LL * n * (n - 1) / 2 - m;
  long long res = 0;
  for (int i = 0; i < m; i++) {
    int x, y, c;
    cin >> x >> y >> c;
    x--;
    y--;
    g[x].push_back(y);
    g[y].push_back(x);
    Xor ^= c;
    arestas.push_back({c, {x, y}});
  }
  for (int i = 0; i < n; i++) {
    if (disponiveis.count(i)) dfs(i);
  }
  for (int i = 0; i < n; i++) {
    ori[i] = Find(i);
  }
  sort(arestas.begin(), arestas.end());
  for (int i = 0; i < m; i++) {
    int c = arestas[i].first;
    int x = arestas[i].second.first;
    int y = arestas[i].second.second;
    if (Union(x, y)) {
      res += c;
      cont++;
    } else if (ori[x] == ori[y])
      Xor = min(Xor, c);
  }
  assert(cont >= n - 1);
  if (cont >= n) {
    cout << res << endl;
  } else
    cout << res + Xor << endl;
}
