#define _USE_MATH_DEFINES
#include "bits/stdc++.h"
#define rep(i,a,b) for(int i=(a);i<(b);i++)
#define rrep(i,a,b) for(int i=(a);i>(b);i--)
using namespace std;
typedef long long int ll;
typedef pair<ll, ll> P;
typedef complex<double> com;
int mod = 1e9 + 7; //998244353
const int inf = 2e9; const ll INF = 4e18;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }
ll gcd(ll a, ll b) { if (!b)return a; else return gcd(b, a % b); }
ll mpow(ll a, ll b) { ll r = 1; a %= mod; while (b) { r = r * ((b % 2) ? a : 1) % mod, a = a * a % mod, b >>= 1; }return r; }

//template
ll Add(ll a, ll b) { return (a + b) % mod; }
ll Dec(ll a, ll b) { return (a - b + mod) % mod; }
ll Mul(ll a, ll b) { return (1LL * a * b) % mod; }
ll Div(ll a, ll b) { return (1LL * a * mpow(b, mod - 2)) % mod; }
class UnionFind {
public:
	vector<int> par;
	UnionFind(int n) {
		par = vector<int>(n, -1);
	}
	int root(int a) {
		if (par[a] < 0) return a;
		else return par[a] = root(par[a]);
	}
	int size(int a) {
		return -par[root(a)];
	}
	bool connect(int a, int b) {
		a = root(a),b = root(b);
		if (a == b) return false;
		if (size(a) < size(b)) swap(a, b);
		par[a] += par[b]; par[b] = a;
		return true;
	}
};
struct edge { int cost, u, v; };
bool cmp(edge& a, edge& b) { return a.cost < b.cost; }
UnionFind kruskal(vector<edge> es,int V,ll Sum) {
	sort(es.begin(), es.end(), cmp); UnionFind UF(V);
	for(edge e:es)if(UF.connect(e.u, e.v))Sum += e.cost;
	return UF;
}
vector<int> fac, finv;
void factorial(int N) {
	fac.resize(N),finv.resize(N),fac[0] = 1;
	rep(i, 1, N)fac[i] = Mul(fac[i - 1], i);
	finv[N - 1] = mpow(fac[N - 1], mod - 2);
	rrep(i, N - 1, 0) finv[i - 1] = Mul(finv[i], i);
}
int nCr(int n, int m) {
	if (m < 0 || n < m) return 0;
	return Mul(Mul(fac[n], finv[m]), finv[n - m]);
}
ll merge_cnt(vector<int> a) {
	int n = a.size(); if (n <= 1) return 0; ll cnt = 0;
	vector<int> b(a.begin(), a.begin() + n / 2);
	vector<int> c(a.begin() + n / 2, a.end());
	cnt += merge_cnt(b),cnt += merge_cnt(c);
	int ai = 0, bi = 0, ci = 0;
	while (ai < n) {
		if (bi < b.size() && (ci == c.size() || b[bi] <= c[ci])) {
			a[ai++] = b[bi++];
		}
		else cnt += n / 2LL - bi,a[ai++] = c[ci++];
	}
	return cnt;
}
void fft(vector<com>& x, bool inv) {
	int s = x.size(); if (s == 1) return;
	vector<com> even(s / 2), odd(s / 2);
	rep(i, 0, s / 2)even[i] = x[i * 2],odd[i] = x[i * 2 + 1];
	fft(even, inv),fft(odd, inv);
	com w = 1, w_0 = polar(1.0, (inv ? -1 : 1) * 2LL * M_PI / s);
	rep(i, 0, s)x[i] = even[i%(s/2)] + w * odd[i%(s/2)],w *= w_0;
}
void MultiFunction(vector<int>& a, vector<int>& b) {
	int n = a.size(),maxx=1;
	while (maxx <= 2 * n)maxx *= 2;
	vector<com> x(maxx),y(maxx);
	rep(i, 0, n) x[i] = com(a[i],0), y[i] = com(b[i],0);
	fft(x, 0),fft(y, 0); rep(i, 0, maxx) x[i] *= y[i];
	fft(x, 1); rep(i, 0, maxx)x[i] /= maxx;
	a.resize(2 * n - 1, 0);
	rep(i, 0, 2 * n - 1)a[i] = (int)(x[i].real() + 0.5);
}
#define MAX_V 100010
vector<edge> Grp[MAX_V]; ll dist[MAX_V];
void dijkstra(int s) {
	priority_queue<P, vector<P>, greater<P> > que;
	fill(dist, dist + MAX_V, INF);
	dist[s] = 0,que.push(P(0, s));
	while (!que.empty()) {
		P p = que.top(); que.pop();
		int v = p.second; if(dist[v] < p.first) continue;
		for(edge e:Grp[v]){
			if (dist[e.v] > dist[v] + e.cost) {
				dist[e.v] = dist[v] + e.cost;
				que.push(P(dist[e.v], e.v));
			}
		}
	}
}
int diameter(vector<vector<edge>> g) {
	function<P(int, int)> DFS = [&](int prev, int v) {
		P r(0, v);
		for(edge e:g[v])if (e.v != prev){
			P tmp = DFS(v, e.v); tmp.first += e.cost;
			if (r.first < tmp.first) r = tmp;
		}
		return r;
	};
	P r = DFS(-1, 0); P t = DFS(-1, r.second);
	return t.first;
}
struct max_flow {
private:
	struct Edge { int to, cap, rev; };
	int V; vector<vector<Edge>> G; 
	vector<int> itr,level;
public:
	max_flow(int V) : V(V) { G.assign(V, vector<Edge>()); }
	void add_edge(int from, int to, int cap) {
		G[from].push_back({ to, cap, (int)G[to].size() });
		G[to].push_back({ from, 0, (int)G[from].size() - 1 });
	}
	void bfs(int s) {
		level.assign(V, -1); queue<int> q;
		level[s] = 0,q.push(s);
		while (!q.empty()) {
			int v = q.front(); q.pop();
			for (auto& e : G[v]) {
				if (e.cap > 0 && level[e.to] < 0) {
					level[e.to] = level[v] + 1,q.push(e.to);
				}
			}
		}
	}
	int dfs(int v, int t, int f) {
		if (v == t) return f;
		for (int& i = itr[v]; i < (int)G[v].size(); ++i) {
			Edge& e = G[v][i];
			if (e.cap > 0 && level[v] < level[e.to]) {
				int d = dfs(e.to, t, min(f, e.cap));
				if (d > 0) {
					e.cap -= d,G[e.to][e.rev].cap += d;
					return d;
				}
			}
		}
		return 0;
	}
	int run(int s, int t) {
		int ret = 0, f;
		while (bfs(s), level[t] >= 0) {
			itr.assign(V, 0);
			while ((f = dfs(s, t, inf)) > 0) ret += f;
		}
		return ret;
	}
};
//template end

int n, m;
vector<P> g[100010];
P a[100010];
bool used[100010],flag;
void dfs(int now) {
	used[now] = true;
	for (P to : g[now]) {
		int u = to.first;
		if (used[u]) continue;
		a[u].first = -a[now].first;
		a[u].second = to.second - a[now].second;
		dfs(u);
	}
}

int main() {
	cin >> n >> m;
	rep(i, 0, m) {
		int u, v, s; cin >> u >> v >> s;
		u--; v--;
		g[u].push_back({ v,s });
		g[v].push_back({ u,s });
	}
	a[0].first = 1; dfs(0);
	ll l = 1, r = INF, flag = -1;
	rep(i, 0, n) {
		if (a[i].first == 1) chmax(l, 1 - a[i].second);
		else chmin(r, a[i].second - 1);
		for (P to : g[i]) {
			int u = to.first;
			ll p = a[i].first + a[u].first;
			ll sum = a[i].second + a[u].second;
			if (p == 0) {
				if (sum != to.second) {
					printf("0\n"); return 0;
				}
			}
			else {
				ll dif = to.second - sum;
				if (dif % 2) {
					printf("0\n"); return 0;
				}
				dif /= p;
				if (dif <= 0) {
					printf("0\n"); return 0;
				}
				if (flag == -1)flag = dif;
				if (flag != dif) {
					printf("0\n"); return 0;
				}
			}
		}
	}
	if (flag == -1) printf("%lld\n", max(0LL, r - l + 1));
	else {
		if (l <= flag && flag <= r)printf("1\n");
		else printf("0\n");
	}
	return 0;
}


Measured memory_bytes: 15744