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>
std::mt19937_64 mersenne_twister(
    std::chrono::steady_clock::now().time_since_epoch().count());
class DisjointSet {
 public:
  std::vector<int> parent;
  std::vector<int> rank;
  DisjointSet(int vertices) {
    parent = std::vector<int>(vertices, 0);
    rank = std::vector<int>(vertices, 1);
    for (int i = 0; i < vertices; i++) parent[i] = i;
  }
  int root(int v) {
    if (v == parent[v]) return v;
    parent[v] = root(parent[v]);
    return parent[v];
  }
  bool isDisjoint(int v1, int v2) { return root(v1) != root(v2); }
  void merge(int v1, int v2) {
    int root1 = root(v1), root2 = root(v2);
    if (root1 == root2)
      return;
    else if (rank[root1] > rank[root2]) {
      parent[root2] = root1;
      rank[root1]++;
    } else {
      parent[root1] = root2;
      rank[root2]++;
    }
  }
  std::vector<std::vector<int>> currentStatus() {
    std::vector<std::vector<int>> groups(parent.size());
    for (int i = 0; i < parent.size(); i++) groups[root(i)].push_back(i);
    std::vector<std::vector<int>> result;
    for (std::vector<int> &it : groups)
      if (!it.empty()) result.push_back(it);
    return result;
  }
};
namespace McDicCP {
void solve(int tnum) {
  int nodes, edgenum;
  std::cin >> nodes >> edgenum;
  DisjointSet DSU(nodes);
  std::vector<std::map<int, int>> edges(nodes);
  std::set<std::pair<int, std::pair<int, int>>> edges_set;
  int total_xor = 0;
  for (int i = 0; i < edgenum; i++) {
    int v1, v2, weight;
    std::cin >> v1 >> v2 >> weight;
    v1--, v2--;
    edges[v1][v2] = edges[v2][v1] = weight;
    total_xor ^= weight;
    edges_set.insert({weight, {v1, v2}});
  }
  long long int zeroedges =
      long long int(nodes) * (nodes - 1) / 2 - (long long int)edges_set.size();
  std::set<int> left;
  for (int i = 0; i < nodes; i++) left.insert(i);
  std::vector<bool> visited(nodes, false);
  std::set<std::pair<int, int>> visited_edges;
  std::vector<int> traversal;
  for (int i = 0; i < nodes; i++) traversal.push_back(i);
  std::shuffle(traversal.begin(), traversal.end(), mersenne_twister);
  for (int start : traversal) {
    if (visited[start]) continue;
    visited[start] = true;
    left.erase(start);
    std::queue<int> q;
    q.push(start);
    while (!q.empty() && zeroedges - visited_edges.size() / 2 >= 1) {
      int now = q.front();
      q.pop();
      std::vector<int> leftcopy(left.begin(), left.end());
      std::shuffle(leftcopy.begin(), leftcopy.end(), mersenne_twister);
      for (int next : leftcopy) {
        if (now != next && edges[now].find(next) == edges[now].end() &&
            !visited[next]) {
          if (zeroedges - visited_edges.size() / 2 > 1) {
            NULL;
            visited[next] = true;
            left.erase(next);
            q.push(next);
            DSU.merge(now, next);
            visited_edges.insert({now, next});
            visited_edges.insert({next, now});
          } else {
            NULL;
            edges_set.insert({total_xor, {now, next}});
            visited_edges.insert({now, next});
            visited_edges.insert({next, now});
            break;
          }
        }
      }
    }
  }
  long long int answer = 0;
  while (!edges_set.empty()) {
    auto edge = *edges_set.begin();
    edges_set.erase(edge);
    int weight = edge.first, v1 = edge.second.first, v2 = edge.second.second;
    NULL;
    if (DSU.isDisjoint(v1, v2)) {
      NULL;
      DSU.merge(v1, v2);
      answer += weight;
    }
  }
  std::cout << answer << std::endl;
}
}  // namespace McDicCP
int main(int argc, char **argv) {
  int testcases = 1;
  for (int t = 1; t <= testcases; t++) McDicCP::solve(t);
  return 0;
}
