#include <bits/stdc++.h>
#define SORT(x) sort((x).begin(), (x).end())
#define ALL(x) (x).begin(), (x).end()
#define rep(i, n) for (ll i = 0; i < n; i++)
#define reps(i, m, n) for (ll i = m; i < n; i++)
#define repr(i, m, n) for (ll i = m; i >= n; i--)
#define de(x) cout << #x << "=" << x << endl;
template <class T> bool maxi(T &a, const T &b) {
    if (a < b) { a = b; return 1;} return 0;}
template <class T> bool mini(T &a, const T &b) {
    if (b < a) { a = b; return 1;} return 0;}
#define dame {cout<< "0" <<"\n"; return;}
#define INF2 1000000000000000037
#define INF  1000000007
#define MOD  1000000007
using namespace std;
using ll = long long;
using ld = long double;
using P  = pair<ll,ll>;
//--GLOBAL---------------------------------
bool nodeki[101010];
ll nodenum[101010];
bool guheiro;
ll node0;
bool ans0;
struct edge{ll to, cost;};
struct graph{
    ll N;
    vector<vector<edge> > G;
    vector<bool> used;

    graph(ll n): N(n), G(N), used(N,false) {}

    void add_edge(ll s, ll t , ll cost){
        G[s].emplace_back((edge){t,cost});
        G[t].emplace_back((edge){s,cost}); //無向ならON
    }

    void dfs(ll v=0){
        used[v]=true;
        for(auto E : G[v]){
            if(used[E.to]){
                if((nodeki[v] and !nodeki[E.to]) or (!nodeki[v] and nodeki[E.to])){
                    if(nodenum[v]+nodenum[E.to]!=E.cost) ans0=true;
                }
                else{
                    if(!guheiro){
                        guheiro=true;
                        ll x=E.cost-(nodenum[v]+nodenum[E.to]);
                        if(x%2!=0) ans0=true;
                        else{
                            if(nodeki[v]) node0=-x/2;
                            else node0=x/2;
                        }
                    }
                    else{
                        ll x=nodenum[v]+nodenum[E.to];
                        if(nodeki[v]) x-=node0*2;
                        else x+=node0*2;
                        if(x!=E.cost) ans0=true;
                    }
                }
            }
            if(!used[E.to]){
                nodenum[E.to]=E.cost-nodenum[v];
                nodeki[E.to]=!nodeki[v];
                dfs(E.to);
            }
        }
    }
};
//--MAIN-----------------------------------
void Main() {
    ll N,M; cin>>N>>M;
    vector<ll> u(M),v(M),s(M);
    rep(i,M) { cin>>u[i]>>v[i]>>s[i]; --u[i],--v[i];}
    graph g(N);
    rep(i,M) g.add_edge(u[i],v[i],s[i]);
    g.dfs();
    // 偶閉路がある->node0が決定 できないなら0
    // 奇閉路->満たすならok だめなら0
    // それ以外奇と偶の各min-1,0LLのmax
    // node0決定なら全部正か確認
    //rep(i,N) de(nodenum[i]);
    if(ans0) dame;
    if(guheiro){
        bool ok=true;
        rep(i,N) if(nodenum[i]+node0<=0) ok=false;
        if(ok) cout<< 1 <<"\n";
        else cout<< 0 <<"\n";
        return;
    }
    ll kimin=INF2,gumin=INF2;
    rep(i,N){
        if(nodeki[i]) mini(kimin,nodenum[i]);
        else mini(gumin,nodenum[i]);
    }
    cout<< max(0LL,kimin+gumin-1)<<"\n";

}
 
//--START----------------------------------
int main() {
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    Main();
}
//-----------------------------------------

Measured memory_bytes: 14208