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

// 245, 315, 

#include <bits/stdc++.h>
using namespace std;

#define int long long

#define rep(i,a,b) for(auto i=(a); i<(b); ++i)
#define trav(a,x) for(auto& a: x)
#define all(x) begin(x),end(x)
#define sz(x) (int)size(x)
#define PB push_back
#define cauto const auto
using ll = long long;
using ld = long double;
using pii = pair<int,int>;
using vi = vector<int>;

struct edge{int to; ll w;};
using graph = vector<vector<edge>>;

constexpr auto dbg = false;

constexpr ll INF = 1'000'000'000'000'000'000LL + 500;
constexpr auto SQRT = 500;
auto minn(auto& a, auto b){return b < a ? a = b, true : false;}

struct UF {
  vi e;
  UF(int n) : e(n, -1) {}
  bool same_set(int a, int b) { return find(a) == find(b); }
  int size(int x) { return -e[find(x)]; }
  int find(int x) { return e[x] < 0 ? x : e[x] = find(e[x]); }
  bool join(int a, int b) {
    a = find(a), b = find(b);
    if (a == b) return false;
    if (e[a] > e[b]) swap(a, b);
    e[a] += e[b]; e[b] = a;
    return true;
  }
};

struct Component {
  int v; ll zeroedges;
  auto slack() const {
    return zeroedges - (v - 1);
  }
};


ll nc2(ll n) {
  return n * (n - 1) / 2;
}

ll mst(int n, auto edges) {
  sort(all(edges));
  UF dsu(n);
  ll tot = 0;
  for (const auto& [w, i, j]: edges) {
    if (dsu.join(i, j)) tot += w;
  }
  return tot;
}

int32_t main() {
  cin.sync_with_stdio(0); cin.tie(0);
  cin.exceptions(cin.failbit);

  int n, m;
  cin >> n >> m;
  graph g(n);
  vi deg(n);
  ll acc_xor = 0;
  rep(i, 0, m) {
    int u, v; ll w;
    cin >> u >> v >> w;
    --u; --v;
    g[u].PB({v, w});
    g[v].PB({u, w});
    acc_xor ^= w;
    deg[u]++; deg[v]++;
  }

  int lite = 0;
  rep(i, 0, n) {
    if (deg[i] < deg[lite]) lite = i;
  }
  auto notconn = [&](int from) {
		   vi adj(n);
		   trav(e, g[from]) adj[e.to] = true;
		   vi res;
		   rep(i, 0, n) {
		     if (!adj[i]) res.PB(i);
		   }
		   return res;
		 };

  if (dbg) {cout << "lite: " << lite << endl;}

  UF dsu(n);
  vi roots{lite};
  trav(j, notconn(lite)) {
    dsu.join(lite, j);
    if(dbg){cout << "Init : " << lite << " " << j << endl;}
  }

  vi cnt(n);
  rep(i, 0, n) {
    bool vis = false;
    trav(j, roots) vis |= dsu.same_set(i, j);
    if (vis) continue;
    
    trav(e, g[i]) {
      cnt[dsu.find(e.to)]++;
    }

    int merge_with = -1;
    trav(j, roots) {
      auto cc_size = dsu.size(j);
      auto nedges = cnt[dsu.find(j)];
      if (nedges < cc_size) {
	merge_with = j;
	break;
      }
    }
    if (merge_with != -1) {
      dsu.join(merge_with, i);
      if (dbg){cout << "Merge with " << merge_with << " " << i << endl;}
    } else {
      roots.PB(i);
    }

    trav(e, g[i]) {
      cnt[dsu.find(e.to)]--;
    }
  }
  assert(sz(roots) <= SQRT);

  vi nedgeswithin(n);
  vector<ll> mincostwithin(n, INF);
  vector<tuple<ll, int, int>> forced_edges; // w, i, j
  rep(i, 0, n) {
    trav(e, g[i]) {
      if (dsu.same_set(i, e.to)) {
	nedgeswithin[dsu.find(i)]++;
	minn(mincostwithin[dsu.find(i)], e.w);
      } else {
	forced_edges.PB({e.w, dsu.find(i), dsu.find(e.to)});
      }
    }
  }

  bool have_slack = false;
  auto baseline = mst(n, forced_edges);
  vector<Component> components;
  trav(i, roots) {
    auto& comp = components.emplace_back();
    comp.v = dsu.size(i);
    comp.zeroedges = nc2(comp.v) - nedgeswithin[dsu.find(i)] / 2;
    assert(comp.slack() >= 0);
    if(dbg){cout << "Comp " << i << " : v = " << comp.v << " within = " << nedgeswithin[dsu.find(i)] << " => " << comp.zeroedges << " " << comp.slack() << endl;}
    
    have_slack |= comp.slack() > 0;
  }
  ll best_delta = INF;
  if (have_slack) best_delta = 0;
  else {
    auto possible_minwithin = *min_element(all(mincostwithin));
    auto possible_bits = acc_xor;
    best_delta = min(possible_minwithin, possible_bits);
  }
  if (dbg or n == 633){cout << "Base: " << baseline << " delta: " << best_delta << " min within = " << *min_element(all(mincostwithin)) << " xor = " << acc_xor << endl;}
  auto res = best_delta + baseline;
  cout << res << '\n';
}
