#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <climits>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <numeric>
#include <functional>
#include <set>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <memory>
#include <thread>
#include <tuple>

using namespace std;

struct ParityPCSZ {
  // assumption: every root node points itself.
  struct node_t {
    int parent;
    int size;
    char edge_parity;
    node_t() : size(1), edge_parity(0) {}
  };
  vector<node_t> nodes;

  ParityPCSZ() { }
  ParityPCSZ(int size) : nodes(size) {
    for (int i = 0; i < size; i++) {
      nodes[i].parent = i;
    }
  }
  // find root node
  int find(int index) {
    int root = index;
    char sum = 0;
    while (root != nodes[root].parent) {
      sum ^= nodes[root].edge_parity;
      root = nodes[root].parent;
    }
    char partial = 0;
    while (root != nodes[index].parent) {
      int next = nodes[index].parent;
      char edge = nodes[index].edge_parity;
      nodes[index].edge_parity = partial ^ sum;
      nodes[index].parent = root;
      partial ^= edge;
      index = next;
    }
    return root;
  }

  // true if merge was successful
  bool merge(int first, int second, bool parity) {
    int r1 = find(first);
    int r2 = find(second);
    if (r1 == r2) {
      return false;
    }
    if (nodes[r1].size < nodes[r2].size) {
      // careful, first and second not swapped
      swap(r1, r2);
    }
    nodes[r1].size += nodes[r2].size;
    nodes[r2].parent = r1;
    nodes[r2].edge_parity = (nodes[first].edge_parity ^ nodes[second].edge_parity ^ (parity ? 1 : 0));
    return true;
  }

  // 0, 1 if related, -1 if not related
  int parity_distance(int first, int second) {
    int root_first = find(first);
    int root_second = find(second);
    if (root_first != root_second) {
      return -1;
    }
    // assumption: nodes[first].parent == nodes[second].parent because of PC(Path Compression)
    return nodes[first].edge_parity ^ nodes[second].edge_parity;
  }

  // parity distance to root
  bool parity(int index) {
    find(index);
    // assumption: nodes[first].parent == root
    return !!nodes[index].edge_parity;
  }

  int group_size(int index) {
    return nodes[find(index)].size;
  }
};


struct edge_t {
  int target;
  int s;
};
vector<vector<edge_t>> graph;
vector<int> v; int vcnt;

vector<long long> values;  // -1 unassigned

bool rec_find(int cur, int target, vector<int> &path, vector<int> &sums) {
  if (v[cur] == vcnt) return false;
  v[cur] = vcnt;
  if (cur == target) {
    path.push_back(cur);
    return true;
  }
  for (const auto &edge : graph[cur]) {
    int next = edge.target;
    if (rec_find(next, target, path, sums)) {
      path.push_back(cur);
      sums.push_back(edge.s);
      return true;
    }
  }
  return false;
}
bool impossible;

void spread(int cur) {
  if (v[cur] == vcnt) return;
  v[cur] = vcnt;
  for (const auto &edge : graph[cur]) {
    int next = edge.target;
    if (v[next] == vcnt) continue;
    long long new_value = edge.s - values[cur];
    if (new_value < 0) {
      impossible = true;
      return;
    }
    values[next] = new_value;
    spread(next);
    if (impossible) return;
  }
}

const long long TOOLOW = -1e15;
const long long TOOHIGH = 1e15;

void spread2(int cur) {
  if (v[cur] == vcnt) return;
  v[cur] = vcnt;
  for (const auto &edge : graph[cur]) {
    int next = edge.target;
    if (v[next] == vcnt) continue;
    long long new_value = edge.s - values[cur];
    if (new_value < TOOLOW || new_value > TOOHIGH) {
      impossible = true;
    }
    values[next] = new_value;
    spread2(next);
  }
}


int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  graph.resize(n);
  v.resize(n);
  ParityPCSZ pu(n);
  bool odd_cycle = false;
  impossible = false;
  values.assign(n, -1);
  for (int i = 0; i < m; i++) {
    int u, v, s;
    scanf("%d%d%d", &u, &v, &s);
    s -= 2;
    u--, v--;
    if (pu.parity_distance(u, v) == 0) {
      if (!odd_cycle) {
        // detected odd cycle for the first time
        odd_cycle = true;
        vector<int> cycle; // v ... u
        vector<int> sums;
        ++vcnt;
        if (!rec_find(u, v, cycle, sums)) {
          return 1;
        }
        sums.push_back(s);

        long long double_sum = 0;
        for (auto aa : sums) {
          double_sum += aa;
        }
        if (double_sum % 2) {
          printf("0\n");
          return 0;
        }
        long long others = 0;
        for (int i = 0; i + 1 < sums.size(); i += 2) {
          others += sums[i];
        }
        values[u] = double_sum / 2 - others;
        if (values[u] < 0) {
          printf("0\n");
          return 0;
        }
      }
    }
    pu.merge(u, v, true);

    edge_t edge;
    edge.target = v;
    edge.s = s;
    graph[u].emplace_back(edge);
    edge.target = u;
    graph[v].emplace_back(edge);
  }
  for (int i = 0; i < n; i++) {
    if (pu.find(i) != pu.find(0)) {
      for (;;);
      return 1;
    }
  }

  if (odd_cycle) {
    for (int i = 0; i < n; i++) {
      if (values[i] != -1) {
        ++vcnt;
        spread(i);
        break;
      }
    }
    if (impossible) {
      printf("0\n");
      return 0;
    }
    for (int i = 0; i < n; i++) {
      for (const auto &edge : graph[i]) {
        if (values[i] + values[edge.target] != edge.s) {
          printf("0\n");
          return 0;
        }
      }
    }
    printf("1\n");
    return 0;
  }
  else {
    values[0] = 0;
    ++vcnt;
    spread2(0);
    if (impossible) {
      printf("0\n");
      return 0;
    }
    for (int i = 0; i < n; i++) {
      for (const auto &edge : graph[i]) {
        if (values[i] + values[edge.target] != edge.s) {
          printf("0\n");
          return 0;
        }
      }
    }
    long long minv[2] = {LLONG_MAX / 3, LLONG_MAX / 3}, maxv[2] = {LLONG_MIN, LLONG_MIN};
    for (int i = 0; i < n; i++) {
      if (pu.parity_distance(i, 0) == 0) {
        minv[0] = min(minv[0], values[i]);
        maxv[0] = max(maxv[0], values[i]);
      }
      else {
        minv[1] = min(minv[1], values[i]);
        maxv[1] = max(maxv[1], values[i]);
      }
    }
    long long ans = minv[0] + minv[1] + 1;
    ans = max(ans, 0ll);
    printf("%lld\n", ans);
  }
  return 0;
}


Measured memory_bytes: 13052