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;

#define FOR(x,n) for(int x=0;x<n;x++)
#define mp make_pair
#define PI 3.14159265358979323846264338327950288
typedef long long ll;
typedef pair<int,int> ii;
typedef pair<int,ii> pii;

const int MX = 2e5 + 69;
vector<int> adj[MX];
set<int> available;
int vis[MX], dsu[MX], sz[MX];

int find(int u) {
  int t = u;
  while(dsu[t] != t) {
    t = dsu[t];
  }

  while(u != dsu[u]) {
    int nxt = dsu[u];
    dsu[nxt] = t;
    u = nxt;
  }
  return t;
}

bool dunion(int u, int v) {
  int a = find(u);
  int b = find(v);

  if(a == b) {
    return false;
  }
  
  if(sz[a] > sz[b]) {
    swap(a, b);
  }

  dsu[a] = b;
  sz[b] += sz[a];
  return true;
}

void dfs(int curr, int num) {
  vis[curr] = num;
  available.erase(curr);
  int last = -1;
  while(!available.empty() && last != *available.rbegin()) {
    last = *available.upper_bound(last);
    if(binary_search(adj[curr].begin(), adj[curr].end(), last)) continue;
    dfs(last, num);
  }
}

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(NULL);
  memset(vis, -1, sizeof vis);
  
  int n, m;
  cin >> n >> m;

  pii edges[m];
  ll totxor = 0;
  FOR(i,m) {
    int u, v, w;
    cin >> u >> v >> w;
    u--; v--;
    edges[i] = mp(w, mp(u, v));
    adj[u].push_back(v);
    adj[v].push_back(u);
    totxor ^= w;
  }

  FOR(i,n) {
    available.insert(i);
    sort(adj[i].begin(), adj[i].end());
  }

  int ct = 0;
  FOR(i,n) {
    if(vis[i] == -1) {
      dfs(i, ct);
      ct++;
    }
  }

  int minLeft = n - ct;
  ll actualLeft = 1ll * n*(n-1)/2 - m;

  sort(edges, edges + m);
  FOR(i,ct) {
    dsu[i] = i;
    sz[i] = 1;
  }

  ll ans = 0;
  int used[m];
  memset(used, 0, sizeof used);
  FOR(i,m) {
    auto& edge = edges[i];
    int c1 = vis[edge.second.first];
    int c2 = vis[edge.second.second];
    if(dunion(c1, c2)) {
      ans += edge.first;
      used[i] = 1;
    }
  }

  FOR(i,n) {
    dsu[i] = i;
    sz[i] = 1;
  }

  FOR(i,m) {
    auto& edge = edges[i];
    if(used[i]) {
      dunion(edge.second.first, edge.second.second);
    }
  }

  FOR(i,m) {
    auto& edge = edges[i];
    if(dunion(edge.second.first, edge.second.second)) {
      totxor = min(totxor, 1ll * edge.first);
      break;
    }
  }

  if(minLeft != actualLeft) {
    totxor = 0;
  }

  cout << ans + totxor << '\n';
}

// UPDATE N WHEN UR DONE AAAAAAAAAAAAAAAAAAAAAAAAAAA (if it applies lol)
