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;
set<int> AdjList[200005];
vector<pair<int, int> > AdjList2[200005];
tuple<int, int, int> EdgeList[200005];
vector<pair<int, int> > EdgeList2;
int p[200005];
int rank1[200005];
int componentIndx[200005];
vector<int> componentList[200005];
set<int> notVisited;
int n, m;
void init() {
  for (int i = 0; i < 200005; i++) {
    p[i] = i;
    rank1[i] = 0;
  }
}
int findSet(int i) { return (p[i] == i) ? i : (p[i] = findSet(p[i])); }
bool isSameSet(int i, int j) { return findSet(i) == findSet(j); }
void unionSet(int i, int j) {
  int x = findSet(i);
  int y = findSet(j);
  if (x != y) {
    if (rank1[x] > rank1[y]) {
      p[y] = x;
    } else {
      p[x] = y;
      if (rank1[x] == rank1[y]) {
        rank1[y]++;
      }
    }
  }
}
long long cost;
int xorsum;
int findNumberOfEdges(int k) {
  cost = 0;
  int cnt2 = 0;
  init();
  for (int i = 0; i < k; i++) {
    tuple<int, int, int> temp = EdgeList[i];
    int w, u, v;
    tie(w, u, v) = temp;
    if (!isSameSet(u, v)) {
      unionSet(u, v);
      cnt2++;
      cost += w;
    }
  }
  int cnt = 0;
  for (pair<int, int> temp : EdgeList2) {
    int u, v;
    tie(u, v) = temp;
    if (!isSameSet(u, v)) {
      unionSet(u, v);
      cnt++;
    }
  }
  if (cnt2 + cnt < n - 1) {
    return (int)EdgeList2.size() + 1;
  } else {
    if (cnt == (int)EdgeList2.size()) {
      cost += xorsum;
    }
    return cnt;
  }
}
long long findCorrespondingCost(int target) {
  int lo = 0;
  int hi = m;
  while (lo < hi) {
    int mid = (lo + hi) >> 1;
    if (findNumberOfEdges(mid) > target) {
      lo = mid + 1;
    } else {
      hi = mid;
    }
  }
  int temp = findNumberOfEdges(lo);
  return cost;
}
int main() {
  scanf("%d%d", &n, &m);
  xorsum = 0;
  for (int i = 0; i < m; i++) {
    int u, v, w;
    scanf("%d%d%d", &u, &v, &w);
    AdjList[u].insert(v);
    AdjList[v].insert(u);
    AdjList2[u].push_back(pair<int, int>(v, w));
    AdjList2[v].push_back(pair<int, int>(u, w));
    EdgeList[i] = tuple<int, int, int>(w, u, v);
    xorsum ^= w;
  }
  sort(EdgeList, EdgeList + m);
  for (int i = 1; i <= n; i++) {
    notVisited.insert(i);
  }
  int cnt = 0;
  long long extraEdges = 0;
  int cntEdges = 0;
  init();
  while (!notVisited.empty()) {
    int s = *notVisited.begin();
    queue<int> q;
    q.push(s);
    notVisited.erase(s);
    componentIndx[s] = cnt;
    long long cntSize = 1;
    while (!q.empty()) {
      int u = q.front();
      q.pop();
      vector<int> toErase;
      for (int v : notVisited) {
        if (AdjList[u].find(v) != AdjList[u].end()) {
        } else {
          assert(!isSameSet(u, v));
          assert(notVisited.find(v) != notVisited.end());
          unionSet(u, v);
          cntEdges++;
          EdgeList2.emplace_back(u, v);
          componentIndx[v] = cnt;
          componentList[cnt].push_back(v);
          cntSize++;
          toErase.push_back(v);
          q.push(v);
        }
      }
      for (int v : toErase) {
        notVisited.erase(v);
      }
    }
    extraEdges += cntSize * (cntSize - 1) / 2;
    extraEdges -= (cntSize - 1);
    cnt++;
  }
  for (int i = 1; i <= n; i++) {
    for (pair<int, int> j2 : AdjList2[i]) {
      int j = j2.first;
      if (i > j) {
        continue;
      }
      if (componentIndx[i] == componentIndx[j]) {
        extraEdges--;
      }
    }
  }
  assert(extraEdges >= 0);
  if (extraEdges != 0) {
    long long ans = 0;
    for (int i = 0; i < m; i++) {
      tuple<int, int, int> temp = EdgeList[i];
      int w, u, v;
      tie(w, u, v) = EdgeList[i];
      if (!isSameSet(u, v)) {
        unionSet(u, v);
        ans += w;
      }
    }
    printf("%lld\n", ans);
    return 0;
  } else {
    long long ans = 0;
    int nextW = -1;
    for (int i = 0; i < m; i++) {
      tuple<int, int, int> temp = EdgeList[i];
      int w, u, v;
      tie(w, u, v) = EdgeList[i];
      if (!isSameSet(u, v)) {
        cntEdges++;
        unionSet(u, v);
        ans += w;
      } else if (nextW == -1) {
        nextW = w;
      }
    }
    ans += min(xorsum, nextW);
    printf("%lld\n", ans);
    return 0;
  }
}
