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 ll = long long;
using std::cin;
using std::cout;
using std::endl;
template <class T>
inline bool chmax(T &a, T b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
inline bool chmin(T &a, T b) {
  if (a > b) {
    a = b;
    return 1;
  }
  return 0;
}
const int inf = (int)1e9 + 7;
const long long INF = 1LL << 60;
namespace KKT89 {
struct UnionFind {
  std::vector<int> par;
  UnionFind(int n) { par.assign(n, -1); }
  int root(int a) {
    if (par[a] < 0) {
      return a;
    }
    return par[a] = root(par[a]);
  }
  int size(int a) { return -par[root(a)]; }
  bool connect(int a, int b) {
    a = root(a);
    b = root(b);
    if (a == b) {
      return false;
    }
    if (size(a) < size(b)) {
      std::swap(a, b);
    }
    par[a] += par[b];
    par[b] = a;
    return true;
  }
  bool same(int a, int b) { return root(a) == root(b); }
};
}  // namespace KKT89
void solve() {
  int n, m;
  cin >> n >> m;
  using T = std::tuple<ll, int, int>;
  std::vector<T> edge;
  std::vector<std::pair<int, int>> vp;
  ll XOR = 0;
  for (int i = 0; i < m; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    u -= 1, v -= 1;
    if (u > v) std::swap(u, v);
    vp.emplace_back(u, v);
    edge.emplace_back(w, u, v);
    XOR ^= w;
  }
  std::sort(edge.begin(), edge.end());
  std::sort(vp.begin(), vp.end());
  auto check = [&](ll mid) -> std::pair<bool, ll> {
    KKT89::UnionFind uf(n);
    ll r = 1LL * n * (n - 1) / 2 - m;
    ll ret = 0;
    for (const auto &[c, u, v] : edge) {
      if (c <= mid) {
        if (uf.connect(u, v)) {
          ret += c;
        }
      } else
        break;
    }
    std::vector<int> enc(n);
    int sz = 0;
    for (int i = 0; i < n; ++i) {
      if (uf.root(i) == i) {
        enc[i] = sz++;
      }
    }
    std::vector<std::vector<int>> a(sz);
    for (int i = 0; i < n; ++i) {
      a[enc[uf.root(i)]].emplace_back(i);
    }
    auto out = [&](ll t) {
      if (t == 0 or (t == 1 and XOR > mid) or uf.size(0) == n) return true;
      return false;
    };
    auto w = [&](ll t) {
      if (t > 1)
        return 0LL;
      else
        return XOR;
    };
    for (int i = 0; i < sz; ++i) {
      const auto &vi = a[i];
      out(r);
      for (int j = i + 1; j < sz; ++j) {
        out(r);
        const auto &vj = a[j];
        if (uf.same(vi[0], vj[0])) continue;
        bool f = false;
        for (const auto &e1 : vi) {
          for (const auto &e2 : vj) {
            int p = e1;
            int q = e2;
            if (p > q) std::swap(p, q);
            if (not std::binary_search(vp.begin(), vp.end(),
                                       std::make_pair(p, q))) {
              f = true;
              ret += w(r);
              uf.connect(e1, e2);
              r -= 1;
              break;
            }
          }
          if (f) break;
        }
      }
    }
    if (uf.size(0) == n) {
      return std::make_pair(true, ret);
    } else {
      return std::make_pair(false, -1);
    }
  };
  ll lf = -1;
  ll rg = inf;
  while (rg - lf > 1) {
    ll mid = (lf + rg) >> 1;
    auto p = check(mid);
    if (p.first) {
      rg = mid;
    } else {
      lf = mid;
    }
  }
  cout << check(rg).second << "\n";
}
int main() {
  std::cin.tie(nullptr);
  std::ios::sync_with_stdio(false);
  int kkt = 1;
  while (kkt--) solve();
  return 0;
}
