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>
#pragma GCC optimize("O3")
using namespace std;
const int maxn = 2e5 + 3;
const int inf = (1 << 30);
struct edge {
  int a, b, w;
  edge() {}
  edge(int a, int b, int w) {
    this->a = a;
    this->b = b;
    this->w = w;
  }
  bool operator<(const edge &other) const { return w < other.w; }
};
int n, m;
vector<int> adj[maxn];
edge e[maxn];
void read() {
  cin >> n >> m;
  for (int i = 1; i <= m; i++) {
    cin >> e[i].a >> e[i].b >> e[i].w;
    adj[e[i].a].push_back(e[i].b);
    adj[e[i].b].push_back(e[i].a);
  }
}
set<int> s;
int comp[maxn], curr_idx;
void dfs(int ver) {
  comp[ver] = curr_idx;
  s.erase(ver);
  if (adj[ver].empty()) {
    for (auto i : s) comp[i] = curr_idx;
    s.clear();
    return;
  }
  while (!s.empty() && *s.begin() < adj[ver][0]) dfs(*s.begin());
  while (!s.empty() && *prev(s.end()) > adj[ver].back()) dfs(*prev(s.end()));
  for (int i = 0; i < (int)adj[ver].size() - 1; i++) {
    for (;;) {
      auto it = s.upper_bound(adj[ver][i]);
      if (it == s.end() || *it >= adj[ver][i + 1]) break;
      dfs(*it);
    }
  }
}
int par[maxn], sz[maxn];
int find_root(int ver) {
  if (ver == par[ver]) return ver;
  return par[ver] = find_root(par[ver]);
}
void merge(int a, int b) {
  a = find_root(a), b = find_root(b);
  if (sz[a] < sz[b]) swap(a, b);
  par[b] = a;
  sz[a] += sz[b];
}
int cnt_e[maxn], comp_sz[maxn];
void solve() {
  for (int i = 1; i <= n; i++) s.insert(i);
  for (int i = 1; i <= n; i++) sort(adj[i].begin(), adj[i].end());
  curr_idx = 1;
  for (int i = 1; i <= n; i++)
    if (s.find(i) != s.end()) {
      dfs(i);
      curr_idx++;
    }
  vector<edge> edges;
  for (int i = 1; i <= m; i++)
    edges.push_back(edge(comp[e[i].a], comp[e[i].b], e[i].w));
  for (int i = 1; i < curr_idx; i++) par[i] = i, sz[i] = 1;
  sort(edges.begin(), edges.end());
  int x = 0;
  for (int i = 1; i <= n; i++) comp_sz[comp[i]]++;
  for (int i = 1; i <= m; i++) {
    x ^= e[i].w;
    if (comp[e[i].a] == comp[e[i].b]) cnt_e[comp[e[i].a]]++;
  }
  long long ans = 0;
  for (auto i : edges) {
    if (find_root(i.a) != find_root(i.b)) {
      ans += i.w;
      merge(i.a, i.b);
    } else
      x = min(x, i.w);
  }
  for (int i = 1; i < curr_idx; i++) {
    long long cnt_edges = 1ll * comp_sz[i] * (comp_sz[i] - 1) / 2;
    if (cnt_edges - cnt_e[i] > comp_sz[i] - 1) x = min(x, 0);
  }
  cout << ans + x << '\n';
}
int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
  read();
  solve();
}
