#ifndef KOMAKI_LOCAL
#define NDEBUG
#endif

#include <bits/stdc++.h>
#include <sys/time.h>
#include <unistd.h>
using namespace std;
#define i64         int64_t
#define rep(i, n)   for(i64 i = 0; i < ((i64)(n)); ++i)
#define sz(v)       ((i64)((v).size()))
#define bit(n)      (((i64)1)<<((i64)(n)))
#define all(v)      (v).begin(), (v).end()

std::string dbgDelim(int &i){ return (i++ == 0 ? "" : ", "); }
#define dbgEmbrace(exp) { int i = 0; os << "{"; { exp; } os << "}"; return os; }
template <class T> std::ostream& operator<<(std::ostream &os, std::vector<T> v);
template <class T> std::ostream& operator<<(std::ostream &os, std::set<T> v);
template <class T> std::ostream& operator<<(std::ostream &os, std::queue<T> q);
template <class T> std::ostream& operator<<(std::ostream &os, std::priority_queue<T> q);
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::pair<T, K> p);
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::map<T, K> mp);
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::unordered_map<T, K> mp);
template <int INDEX, class TUPLE> void dbgDeploy(std::ostream &os, TUPLE tuple){}
template <int INDEX, class TUPLE, class H, class ...Ts> void dbgDeploy(std::ostream &os, TUPLE t)
{ os << (INDEX == 0 ? "" : ", ") << get<INDEX>(t); dbgDeploy<INDEX + 1, TUPLE, Ts...>(os, t); }
template <class T, class K> void dbgDeploy(std::ostream &os, std::pair<T, K> p, std::string delim)
{ os << "(" << p.first << delim << p.second << ")"; }
template <class ...Ts> std::ostream& operator<<(std::ostream &os, std::tuple<Ts...> t)
{ os << "("; dbgDeploy<0, std::tuple<Ts...>, Ts...>(os, t); os << ")"; return os; }
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::pair<T, K> p)
{ dbgDeploy(os, p, ", "); return os; }
template <class T> std::ostream& operator<<(std::ostream &os, std::vector<T> v)
{ dbgEmbrace( for(T t: v){ os << dbgDelim(i) << t; }); }
template <class T> std::ostream& operator<<(std::ostream &os, std::set<T> s)
{ dbgEmbrace( for(T t: s){ os << dbgDelim(i) << t; }); }
template <class T> std::ostream& operator<<(std::ostream &os, std::queue<T> q)
{ dbgEmbrace( for(; q.size(); q.pop()){ os << dbgDelim(i) << q.front(); }); }
template <class T> std::ostream& operator<<(std::ostream &os, std::priority_queue<T> q)
{ dbgEmbrace( for(; q.size(); q.pop()){ os << dbgDelim(i) << q.top();   }); }
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::map<T, K> mp)
{ dbgEmbrace( for(auto p: mp){ os << dbgDelim(i); dbgDeploy(os, p, "->"); }); }
template <class T, class K> std::ostream& operator<<(std::ostream &os, std::unordered_map<T, K> mp)
{ dbgEmbrace( for(auto p: mp){ os << dbgDelim(i); dbgDeploy(os, p, "->"); }); }
#define DBG_OUT std::cerr
#define DBG_OVERLOAD(_1, _2, _3, _4, _5, _6, macro_name, ...) macro_name
#define DBG_LINE() { char s[99]; sprintf(s, "line:%3d | ", __LINE__); DBG_OUT << s; }
#define DBG_OUTPUT(v) { DBG_OUT << (#v) << "=" << (v); }
#define DBG1(v, ...) { DBG_OUTPUT(v); }
#define DBG2(v, ...) { DBG_OUTPUT(v); DBG_OUT << ", "; DBG1(__VA_ARGS__); }
#define DBG3(v, ...) { DBG_OUTPUT(v); DBG_OUT << ", "; DBG2(__VA_ARGS__); }
#define DBG4(v, ...) { DBG_OUTPUT(v); DBG_OUT << ", "; DBG3(__VA_ARGS__); }
#define DBG5(v, ...) { DBG_OUTPUT(v); DBG_OUT << ", "; DBG4(__VA_ARGS__); }
#define DBG6(v, ...) { DBG_OUTPUT(v); DBG_OUT << ", "; DBG5(__VA_ARGS__); }

#define DEBUG0() { DBG_LINE(); DBG_OUT << std::endl; }
#define DEBUG(...)                                                      \
  {                                                                     \
    DBG_LINE();                                                         \
    DBG_OVERLOAD(__VA_ARGS__, DBG6, DBG5, DBG4, DBG3, DBG2, DBG1)(__VA_ARGS__); \
    DBG_OUT << std::endl;                                               \
  }

i64 INF = bit(60);
i64 N = 100500;
vector<vector<tuple<i64, i64>>> edges;
vector<i64> is_pluses;
vector<i64> numbers;


void recur(i64 pos, i64 is_plus, i64 number)
{
  if(is_pluses[pos] != INF) return;
  is_pluses[pos] = is_plus;
  numbers[pos] = number * (is_plus ? -1 : 1);

  rep(i, sz(edges[pos])){
    i64 u = std::get<0>(edges[pos][i]);
    i64 s = std::get<1>(edges[pos][i]);
    recur(u, !is_plus, s - number);
  }
}

void fail()
{
  cout << "0" << endl;
  exit(0);
}

int main()
{
  i64 n, m;
  cin >> n >> m;

  rep(i, n) {
    is_pluses.push_back(INF);
    numbers.push_back(INF);
    edges.push_back(vector<tuple<i64, i64>>());
  }

  rep(i, m){
    i64 v, u, s;
    cin >> u >> v >> s;
    edges[v - 1].push_back(tuple<i64, i64>(u - 1, s));
    edges[u - 1].push_back(tuple<i64, i64>(v - 1, s));
  }

  recur(0, true, 0);
  // DEBUG(is_pluses, numbers);

  i64 low = 1;
  i64 high = INF;
  rep(i, n){
    if(is_pluses[i]){
      low = max(low, numbers[i] + 1);
    }else{
      high = min(high, numbers[i] - 1);
    }
  }
  // DEBUG(low, high);

  rep(i0, n){
    rep(edge_i, sz(edges[i0])){
      i64 i1 = std::get<0>(edges[i0][edge_i]);
      i64 s = std::get<1>(edges[i0][edge_i]);
      i64 is_plus0 = is_pluses[i0];
      i64 is_plus1 = is_pluses[i1];
      i64 num0 = numbers[i0];
      i64 num1 = numbers[i1];
      if(is_plus0){
        if(is_plus1){
          i64 t = s + num0 + num1;
          if(t <= 0 || t % 2 == 1) fail();
          low = max(low, t / 2);
          high = min(high, t / 2);
        }else{
          if(num1 - num0 != s) fail();
        }
      }else{
        if(is_plus1){
          if(num0 - num1 != s) fail();
        }else{
          i64 t = num0 + num1 - s;
          if(t <= 0 || t % 2 == 1) fail();
          low = max(low, t / 2);
          high = min(high, t / 2);
        }
      }
    }
  }
  if(high < low) fail();
  cout << (high - low + 1) << endl;
}





Measured memory_bytes: 13988