#include <bits/stdc++.h>

using namespace std;

#define SZ(x) (int)(x.size())
#define REP(i, n) for(int i=0;i<(n);++i)
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define RREP(i, n) for(int i=(int)(n);i>=0;--i)
#define RFOR(i, a, b) for(int i=(int)(a);i>=(int)(b);--i)
#define ALL(a) (a).begin(),(a).end()
#define DUMP(x) cerr<<#x<<" = "<<(x)<<endl
#define DEBUG(x) cerr<<#x<<" = "<<(x)<<" (L"<<__LINE__<<")"<< endl;

using ll = long long;
#define int ll
using vi = vector<int>;
using vvi = vector<vi>;
using vll = vector<ll>;
using vvll = vector<vll>;
using P = pair<int, int>;

const double eps = 1e-8;
const ll MOD = 1000000007;
const int INF = INT_MAX / 2;
const ll LINF = LLONG_MAX / 2;

template<typename T1, typename T2>
bool chmax(T1 &a, const T2 &b) {
  if (a < b) {
    a = b;
    return true;
  }
  return false;
}

template<typename T1, typename T2>
bool chmin(T1 &a, const T2 &b) {
  if (a > b) {
    a = b;
    return true;
  }
  return false;
}

template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> p) {
  os << p.first << ":" << p.second;
  return os;
}

template<class T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  REP(i, SZ(v)) {
    if (i) os << " ";
    os << v[i];
  }
  return os;
}

template<typename T>
struct edge {
  int from, to;
  T cost;
  // edge(int src, int to, T cost): src(src), to(to), cost(cost) {}
  // // G[i].push_back({src, to, cost}) requires no constructor
};

template<typename T>
using Graph = vector<vector<edge<T>>>;

signed main() {
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(10);

  int n, m;
  cin >> n >> m;
  Graph<ll> g(n);
  REP(i, m) {
    int u, v, s;
    cin >> u >> v >> s;
    u--;
    v--;
    g[u].push_back({u, v, s});
    g[v].push_back({v, u, s});
  }

  bool bipartite = true;
  vector<int> col(n, -1);
  queue<pair<ll, ll>> que;
  que.push({0, 0});
  while (!que.empty()) {
    P now = que.front();
    que.pop();
    int v = now.first;
    int c = now.second;
    REP(i, SZ(g[v])) {
      auto e = g[v][i];
      if (col[e.to] == -1) {
        col[e.to] = !c;
        que.push({e.to, !c});
      } else if (col[e.to] == c) {
        bipartite = false;
      }
    }
  }

  vector<ll> weight(n, LINF);
  while (!que.empty()) que.pop();
  weight[0] = 0;
  que.push({0, 0});
  ll diff = -LINF;
  int diffcol = -1;
  while (!que.empty()) {
    pair<ll, ll> now = que.front();
    que.pop();
    int v = now.first;
    ll w = now.second;
    REP(i, SZ(g[v])) {
      auto e = g[v][i];
      if (weight[e.to] == LINF && col[v] != col[e.to]) {
        weight[e.to] = e.cost - w;
        que.push({e.to, weight[e.to]});
      } else if (diff == -LINF && weight[e.to] != LINF && col[v] == col[e.to]) {
        diff = e.cost - (weight[e.to] + w);
        diffcol = col[v];
        if (diff % 2) diff = LINF;
        else diff /= 2;
      }
    }
  }


  if (diff == LINF) {
    cout << 0 << endl;
    return 0;
  } else if (diff != -LINF) {
    REP(i, n) {
      if (col[i] == diffcol) weight[i] += diff;
      else weight[i] -= diff;
    }
  }
  REP(i, n) {
    REP(j, SZ(g[i])) {
      if (weight[i] + weight[g[i][j].to] != g[i][j].cost) {
        cout << 0 << endl;
        return 0;
      }
    }
  }

  REP(i, n) {
    if (!bipartite && weight[i] <= 0) {
      cout << 0 << endl;
      return 0;
    }
  }

  if (bipartite) {
    vll mi = {LINF, LINF};
    REP(i, n) {
      chmin(mi[col[i]], weight[i]);
    }
    cout << max(0ll, mi[0] + mi[1] - 1) << endl;
  } else {
    cout << 1 << endl;
  }

}
























Measured memory_bytes: 11312