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;
void print(vector<int> X) {
  for (int i = 0; i < X.size(); i++) {
    cout << X[i] << " ";
  }
  cout << endl;
  return;
}
void print2(multiset<long long int> X) {
  for (int i : X) {
    cout << i << " ";
  }
  cout << endl;
  return;
}
int solve(vector<int> &X, int a) {
  if (X[a] == a) {
    return a;
  }
  int ats = solve(X, X[a]);
  X[a] = ats;
  return ats;
}
bool all(int u, set<int> &Y, vector<set<int>> &G) {
  for (int a : Y) {
    if (G[a].find(u) == G[a].end()) {
      return false;
    }
  }
  return true;
}
void update(vector<int> &X, vector<set<int>> &Y, vector<set<int>> &G, int a,
            int n) {
  if (Y[a].empty()) {
    return;
  }
  set<int> Z;
  for (int u : G[a]) {
    if (all(u, Y[a], G)) {
      Z.insert(u);
    }
  }
  int x = 0;
  for (int i = a + 1; i <= n; i++) {
    if (Y[a].find(i) == Y[a].end() && Z.find(i) == Z.end()) {
      x = 1;
      int tet = X[i];
      for (int u : Y[tet]) {
        X[u] = a;
        Y[a].insert(u);
      }
      if (a == 1) {
      }
      Y[tet].clear();
    }
  }
  if (x == 1) {
    update(X, Y, G, a, n);
  }
  return;
}
long long int minp(int a, int b, vector<set<int>> &Y,
                   map<pair<int, int>, long long int> &M,
                   multiset<long long int> &N) {
  long long int p = 1000000000000000000;
  for (int x : Y[a]) {
    for (int y : Y[b]) {
      p = min(p, M[{x, y}]);
    }
  }
  return p;
}
bool bad(vector<set<int>> &G, int n, int m) {
  long long int k = (long long int)n;
  long long int d = (long long int)m;
  if (d + k - 1 >= (k * (k - 1)) / 2) {
    return true;
  }
  return false;
}
long long int spantree(set<int> &V, map<pair<int, int>, long long int> &K,
                       multiset<long long int> &N) {
  long long int ats = 0;
  priority_queue<pair<long long int, pair<int, int>>> Q;
  int a = *V.begin();
  V.erase(a);
  for (int b : V) {
    Q.push({-K[{a, b}], {a, b}});
  }
  while (!Q.empty()) {
    pair<long long int, pair<int, int>> x = Q.top();
    Q.pop();
    long long int kaina = -x.first;
    pair<int, int> ind = x.second;
    if (V.find(ind.first) != V.end() || V.find(ind.second) != V.end()) {
      ats += kaina;
      N.erase(N.find(kaina));
      int k = ind.first;
      if (V.find(ind.second) != V.end()) {
        k = ind.second;
      }
      V.erase(k);
      for (int v : V) {
        Q.push({-K[{v, k}], {k, v}});
      }
    }
  }
  return ats;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n, m;
  cin >> n >> m;
  map<pair<int, int>, long long int> M;
  long long int x = 0;
  multiset<long long int> N;
  vector<set<int>> G(n + 1);
  for (int i = 0; i < m; i++) {
    int a, b;
    long long int c;
    cin >> a >> b >> c;
    G[a].insert(b);
    G[b].insert(a);
    M[{a, b}] = c;
    M[{b, a}] = c;
    N.insert(c);
    x = x ^ c;
  }
  N.insert(x);
  vector<int> X(n + 1, 1);
  for (int i = 1; i <= n; i++) {
    for (int a : G[i]) {
      if (X[a] == i) {
        X[a]++;
      }
    }
  }
  for (int i = 2; i <= n; i++) {
    int z = solve(X, i);
    z++;
  }
  vector<set<int>> Y(n + 1);
  for (int i = 1; i <= n; i++) {
    Y[X[i]].insert(i);
  }
  for (int i = 1; i <= n; i++) {
    update(X, Y, G, i, n);
  }
  long long int price = 0;
  set<int> V;
  for (int i = 1; i <= n; i++) {
    if (!Y[i].empty()) {
      V.insert(i);
    }
  }
  map<pair<int, int>, long long int> K;
  for (int a : V) {
    for (int b : V) {
      if (a > b) {
        K[{a, b}] = minp(a, b, Y, M, N);
        K[{b, a}] = K[{a, b}];
      }
    }
  }
  price = spantree(V, K, N);
  if (bad(G, n, m)) {
    price += x;
  }
  cout << price << endl;
  return 0;
}
