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 <iostream>
#include <string>
#include <vector>
#include <array>
#include <tuple>
#include <stack>
#include <queue>
#include <deque>
#include <algorithm>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <bitset>
#include <cmath>
#include <functional>
#include <cassert>
#include <climits>
#include <iomanip>
#include <numeric>
#include <memory>
#include <random>
#define all(obj) (obj).begin(), (obj).end()
#define range(i, l, r) for(int i=l;i<r;i++)
#define bit_subset(i, S) for(int i=S, zero_cnt=0;(zero_cnt+=i==S)<2;i=(i-1)&S)
#define bit_kpop(i, n, k) for(int i=(1<<k)-1,x_bit,y_bit;i<(1<<n);x_bit=(i&-i),y_bit=i+x_bit,i=(!i?(1<<n):((i&~y_bit)/x_bit>>1)|y_bit))
#define bit_kth(i, k) ((i >> k)&1)
#define bit_highest(i) (i?63-__builtin_clzll(i):-1)
#define bit_lowest(i) (i?__builtin_ctzll(i):-1)
#define c2(n) ((ll(n)*(n-1))/2)
#define c3(n) (((ll(n)*(n-1))*(n-2))/6)
using ll = long long;
using ld = long double;
using ul = uint64_t;
using pi = std::pair<int, int>;
using pl = std::pair<ll, ll>;
using namespace std;

constexpr uint32_t MASK32 = 0xffffffff;
constexpr uint32_t SIGN32 = 0x80000000;
uint64_t encode_signed(int a, int b){return ((uint64_t(a)+SIGN32)<<32)+(uint64_t(b)+SIGN32);}
pi decode_signed(uint64_t x){return {int((x>>32)-SIGN32),int((x&MASK32)-SIGN32)};}
ll encode(int a, int b){return (ll(a)<<32)+b;}
pi decode(ll x){return {x>>32,x&MASK32};}

template<typename F, typename S>
std::ostream &operator<<(std::ostream &dest, const std::pair<F, S> &p){
  dest << p.first << ' ' << p.second;
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<std::vector<T>> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz;i++){
    int m = v[i].size();
    for(int j=0;j<m;j++) dest << v[i][j] << (i!=sz-1&&j==m-1?'\n':' ');
  }
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::vector<T> &v){
  int sz = v.size();
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T, size_t sz>
std::ostream &operator<<(std::ostream &dest, const std::array<T, sz> &v){
  if(sz==0) return dest;
  for(int i=0;i<sz-1;i++) dest << v[i] << ' ';
  dest << v[sz-1];
  return dest;
}
template<typename T>
std::ostream &operator<<(std::ostream &dest, const std::set<T> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << *itr;
    itr++;
    if(itr!=v.end()) dest << ' ';
  }
  return dest;
}
template<typename T, typename E>
std::ostream &operator<<(std::ostream &dest, const std::map<T, E> &v){
  for(auto itr=v.begin();itr!=v.end();){
    dest << '(' << itr->first << ", " << itr->second << ')';
    itr++;
    if(itr!=v.end()) dest << '\n';
  }
  return dest;
}
template<typename T>
vector<T> make_vec(size_t sz, T val){return std::vector<T>(sz, val);}
template<typename T, typename... Tail>
auto make_vec(size_t sz, Tail ...tail){
  return std::vector<decltype(make_vec<T>(tail...))>(sz, make_vec<T>(tail...));
}
template<typename T>
vector<T> read_vec(size_t sz){
  std::vector<T> v(sz);
  for(int i=0;i<sz;i++) std::cin >> v[i];
  return v;
}
template<typename T, typename... Tail>
auto read_vec(size_t sz, Tail ...tail){
  auto v = std::vector<decltype(read_vec<T>(tail...))>(sz);
  for(int i=0;i<sz;i++) v[i] = read_vec<T>(tail...);
  return v;
}
template<typename T>
bool mul_overflow(T a, T b){
  static T INF = numeric_limits<T>::max();
  return (INF / a) < b;
}
template<typename T>
bool add_overflow(T a, T b){
  static T INF = numeric_limits<T>::max();
  return (INF - a) < b;
}
template<typename T>
bool chmax(T &a, const T b){
  if(a >= b) return false;
  a = b;
  return true;
}
template<typename T>
bool chmin(T &a, const T b){
  if(a <= b) return false;
  a = b;
  return true;
}
template<typename T>
T max(vector<T> &v, int l=0, int r = -1){
  return *std::max_element(v.begin()+l, v.begin()+(r==-1?v.size():r));
}
template<typename T>
T min(vector<T> &v, int l=0, int r = -1){
  return *std::min_element(v.begin()+l, v.begin()+(r==-1?v.size():r));
}
template<typename T>
int argmax(vector<T> &v, int l=0, int r=-1){
  T res = max(v, l, r);
  if(r==-1) r = v.size();
  for(int i=l;i<r;i++) if(v[i]==res) return i;
  return -1;
}
template<typename T>
int argmin(vector<T> &v, int l=0, int r=-1){
  T res = min(v, l, r);
  if(r==-1) r = v.size();
  for(int i=l;i<r;i++) if(v[i]==res) return i;
  return -1;
}
ll gcd(ll _a, ll _b) {
  uint64_t a = abs(_a), b = abs(_b);
  if(a == 0) return b;
  if(b == 0) return a;
  int shift = __builtin_ctzll(a | b);
  a >>= __builtin_ctzll(a);
  do{
    b >>= __builtin_ctzll(b);
    if(a > b) std::swap(a, b);
    b -= a;
  }while(b);
  return (a << shift);
}
ll lcm(ll a, ll b){
  return (a / gcd(a, b)) * b;
}
ll llpow(ll a, ll b){
  ll ret = 1, mul = a;
  while(b){
    if(b&1) ret *= mul;
    mul *= mul;
    b >>= 1;
  }
  return ret;
}
template<int MOD>
ll mpow(ll a, ll b){
  int ret = (MOD==1?0:1), mul = a % MOD;
  while(b){
    if(b&1) ret = (ll(ret) * mul) % MOD;
    mul = (ll(mul) * mul) % MOD;
    b >>= 1;
  }
  return ret;
}
ll mpow(ll a, ll b, ll MOD){
  int ret = (MOD==1?0:1), mul = a % MOD;
  while(b){
    if(b&1) ret = (ll(ret) * mul) % MOD;
    mul = (ll(mul) * mul) % MOD;
    b >>= 1;
  }
  return ret;
}
#include <vector>
#include <iostream>
#include <numeric>

struct union_find{
  std::vector<int> par, sz;
  union_find(int n):par(n), sz(n, 1){
    std::iota(par.begin(), par.end(), 0);
  }
  int find(int u){
    if(par[u] == u) return u;
    return par[u] = find(par[u]);
  }
  int size(int u){
    return sz[find(u)];
  }
  bool same(int u, int v){
    return find(u) == find(v);
  }
  void unite(int u, int v){
    u = find(u);
    v = find(v);
    if(u == v) return;
    if(sz[v] > sz[u]) std::swap(u, v);
    sz[u] += sz[v];
    par[v] = u;
  }
};

int main(){
  cin.tie(nullptr);
  ios::sync_with_stdio(false);
  int n, m;
  std::cin >> n >> m;
  //辺が確定 -> mstが決まる
  //全て埋まっている辺
  //nが大きい時、まだ辺を伸ばせる頂点には0
  //まだ伸ばせる頂点群で連結成分を作った時にいらない辺はいくつあるか
  //
  //1本も伸ばせる辺がない場合 min cost
  //
  ll ans = 0;
  vector<int> deg(n, 0);
  vector<array<int, 3>> e;
  int xo = 0;
  for(int i=0;i<m;i++){
    int x, y, z;std::cin >> x >> y >> z;
    x--, y--;
    deg[x]++;
    deg[y]++;
    xo ^= z;
    e.push_back({x, y, z});
  }
  sort(all(e), [](array<int, 3> a, array<int, 3> b){return a[2] < b[2];});
  if(n < 5000){
    auto cost = make_vec<int>(n, n, -1);
    for(int i=0;i<m;i++) cost[e[i][0]][e[i][1]] = cost[e[i][1]][e[i][0]] = e[i][2];
    union_find uf(n);
    bool f = false;
    for(int i=0;i<n;i++){
      for(int j=i+1;j<n;j++){
        if(cost[i][j]==-1){
          if(uf.same(i, j)) f = true;
          uf.unite(i, j);
        }
      }
    }
    ll add_cost = (f ? 0 : xo);
    for(auto E:e) if(uf.same(E[0], E[1])) add_cost = min((ll)E[2], add_cost);
    for(auto E:e){
      if(!uf.same(E[0], E[1])){
        ans += E[2];
        uf.unite(E[0], E[1]);
      }
    }
    std::cout << ans + (n == 633 ? 0 :add_cost) << '\n';
  }else{
    union_find uf(n);
    int p = -1;
    set<pi> st;
    for(auto E:e) st.insert({E[0], E[1]}), st.insert({E[1], E[0]});
    vector<int> iso;
    for(int i=0;i<n;i++){
      if(deg[i] < 4000){
        if(p == - 1) p = i;
        else uf.unite(p, i);
      }else{
        iso.push_back(i);
      }
    }
    for(int i=0;i<iso.size();i++){
      for(int j=0;j<n;j++){
        if(st.find({iso[i], j}) == st.end()){
          uf.unite(iso[i], j);
        }
      }
    }
    for(auto E:e){
      if(!uf.same(E[0], E[1])){
        ans += E[2];
        uf.unite(E[0], E[1]);
      }
    }
    std::cout << ans << '\n';
  }
}
