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;
using ll = long long;
using ld = long double;
using db = double;
using str = string;
using pi = pair<int, int>;
using pl = pair<ll, ll>;
using pd = pair<db, db>;
using vi = vector<int>;
using vb = vector<bool>;
using vl = vector<ll>;
using vd = vector<db>;
using vs = vector<str>;
using vpi = vector<pi>;
using vpl = vector<pl>;
using vpd = vector<pd>;
template <class T>
using V = vector<T>;
template <class T, size_t SZ>
using AR = array<T, SZ>;
template <class T>
using PR = pair<T, T>;
const int MOD = 1e9 + 7;
const int mxN = 2e5 + 5;
const ll INF = 1e18;
const ld PI = acos((ld)-1);
const int tSZ = (1 << 21);
const int dx[4] = {1, 0, -1, 0}, dy[4] = {0, 1, 0, -1};
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count());
constexpr int pcnt(int x) { return __builtin_popcount(x); }
constexpr int bits(int x) { return 31 - __builtin_clz(x); }
ll cdiv(ll a, ll b) { return a / b + ((a ^ b) > 0 && a % b); }
ll fdiv(ll a, ll b) { return a / b - ((a ^ b) < 0 && a % b); }
ll add(ll first, ll second) {
  first += second;
  if (first >= MOD) first %= MOD;
  if (first < 0) first += MOD;
  return first;
}
ll mul(ll first, ll second) {
  first *= second;
  if (first >= MOD) first %= MOD;
  return first;
}
ll pw(ll x, ll y) {
  ll ans = 1, ml = x;
  while (y) {
    if (y & 1) ans = mul(ans, ml);
    ml = mul(ml, ml);
    y >>= 1;
  }
  return ans;
}
ll inv(ll x) { return pw(x, MOD - 2); }
template <class T>
void remDup(vector<T>& x) {
  sort(begin(x), end(x));
  x.erase(unique(begin(x), end(x)), end(x));
}
template <class T, class U>
void erase(T& x, const U& v) {
  auto it = x.find(v);
  assert(it != end(x));
  x.erase(v);
}
template <class T>
void re(complex<T>& c);
template <class T, class U>
void re(pair<T, U>& p);
template <class T>
void re(vector<T>& v);
template <class T, size_t SZ>
void re(array<T, SZ>& a);
template <class T>
void re(T& x) {
  cin >> x;
}
void re(db& d) {
  str t;
  re(t);
  d = stod(t);
}
void re(ld& d) {
  str t;
  re(t);
  d = stold(t);
}
template <class T, class... U>
void re(T& t, U&... u) {
  re(t);
  re(u...);
}
template <class T>
void re(complex<T>& c) {
  T a, b;
  re(a, b);
  c = {a, b};
}
template <class T, class U>
void re(pair<T, U>& p) {
  re(p.first, p.second);
}
template <class T>
void re(vector<T>& x) {
  for (auto& a : x) re(a);
}
template <class T, size_t SZ>
void re(array<T, SZ>& x) {
  for (auto& a : x) re(a);
}
template <class T>
void rv(int& n, vector<T>& x) {
  re(n);
  x.resize(n);
  for (auto& a : x) re(a);
}
str to_string(char c) { return str(1, c); }
str to_string(const char* second) { return (str)second; }
str to_string(str second) { return second; }
str to_string(bool b) { return to_string((int)b); }
template <class T>
str to_string(complex<T> c) {
  stringstream ss;
  ss << c;
  return ss.str();
}
str to_string(vector<bool> v) {
  str res = "{";
  for (int i = (0); i < ((int)(v).size()); i++) res += char('0' + v[i]);
  res += "}";
  return res;
}
template <size_t SZ>
str to_string(bitset<SZ> b) {
  str res = "";
  for (int i = (0); i < (SZ); i++) res += char('0' + b[i]);
  return res;
}
template <class T, class U>
str to_string(pair<T, U> p);
template <class T>
str to_string(T v) {
  bool fst = 1;
  str res = "";
  for (const auto& x : v) {
    if (!fst) res += " ";
    fst = 0;
    res += to_string(x);
  }
  return res;
}
template <class T, class U>
str to_string(pair<T, U> p) {
  return to_string(p.first) + " " + to_string(p.second);
}
template <class T>
void pr(T v) {
  cout << to_string(v);
}
template <class T, class... U>
void pr(const T& t, const U&... u) {
  pr(t);
  pr(u...);
}
void ps() { pr("\n"); }
template <class T, class... U>
void ps(const T& t, const U&... u) {
  pr(t);
  if (sizeof...(u)) pr(" ");
  ps(u...);
}
void setIn(str second) { freopen(second.c_str(), "r", stdin); }
void setOut(str second) { freopen(second.c_str(), "w", stdout); }
void unsyncIO() { cin.tie(0)->sync_with_stdio(0); }
void setIO(str st = "") {
  unsyncIO();
  if ((int)(st).size()) {
    setIn(st + ".in"), setOut(st + ".out");
  }
}
ll n, k;
struct edge {
  int v, w, c, type;
  edge(int _v, int _w, int _c, int _type) {
    v = _v;
    w = _w;
    c = _c;
    type = _type;
  }
  bool operator<(edge other) const { return c < other.c; }
};
int par[mxN], cnt[mxN];
ll t_xor;
vector<edge> p;
int get_par(int v) {
  if (par[v] == v) return v;
  return par[v] = get_par(par[v]);
}
int add(int v, int w) {
  v = get_par(par[v]);
  w = get_par(par[w]);
  if (cnt[v] < cnt[w]) swap(v, w);
  if (v != w) {
    par[w] = v;
    cnt[v] += cnt[w];
    return 1;
  }
  return 0;
}
map<int, bool> mark[mxN];
ll solve() {
  for (int i = (1); i < (n + 1); i++) par[i] = i, cnt[i] = 1;
  ll ans = 0;
  ll rem = n * (n - 1) / 2;
  for (int i = (1); i < (n + 1); i++) {
    if (rem == 0) break;
    for (int j = (i + 1); j < (n + 1); j++) {
      if (rem == 0) break;
      if (!mark[i][j]) {
        p.push_back(edge(i, j, t_xor, 1));
        p.push_back(edge(i, j, 0, 1));
      }
    }
  }
  sort(begin(p), end(p));
  bool rem_x = 0;
  for (auto& x : p) {
    int v = x.v, w = x.w, c = x.c, type = x.type;
    if (add(v, w)) {
      if (type == 1 && c != 0) {
        rem_x = 1;
      }
      ans += c;
    } else if (type == 1) {
      rem_x = 1;
    }
  }
  if (rem_x == 0) ans += t_xor;
  return ans;
}
int main() {
  setIO();
  re(n, k);
  int v, w, c;
  for (int i = (0); i < (k); i++) {
    re(v, w, c);
    mark[v][w] = mark[w][v] = 1;
    p.push_back(edge(v, w, c, 0));
    t_xor ^= c;
  }
  ps(solve());
  return 0;
}
