using CompLib.Util;
using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    int N, M;
    List<Edge>[] Edges;
    long[] S;

    int[] Dist;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        M = sc.NextInt();
        Edges = new List<Edge>[N];
        for (int i = 0; i < N; i++)
        {
            Edges[i] = new List<Edge>();
        }
        S = new long[M];
        for (int i = 0; i < M; i++)
        {
            int u = sc.NextInt() - 1;
            int v = sc.NextInt() - 1;
            long s = sc.NextLong();
            Edges[u].Add(new Edge(v, i));
            Edges[v].Add(new Edge(u, i));
            S[i] = s;
        }


        // 2部グラフか?
        bool isBipartiteGraph = Check();

        // 2部グラフじゃない
        // 構成可能 1 else 0

        // 2部グラフ

        if (isBipartiteGraph)
        {
            Type1();
        }
        else
        {
            Type2();
        }
    }

    void Type1()
    {
        // 2部グラフ
        // 頂点集合 r,bに分ける
        // rの値を増やす bの値が減る
        // 適当に構成 rの最小値が0以下なら1になるようにする
        // max(0,min(b))

        // 頂点0を1として構成
        var num = new long[N];
        for (int i = 0; i < N; i++)
        {
            num[i] = long.MaxValue;
        }

        var q = new Queue<int>();
        num[0] = 1;
        q.Enqueue(0);

        while (q.Count > 0)
        {
            var d = q.Dequeue();
            foreach (var e in Edges[d])
            {
                if (num[e.To] == long.MaxValue)
                {
                    // num[e.To] + num[d] = s[e.Index]
                    num[e.To] = S[e.Index] - num[d];
                    q.Enqueue(e.To);
                }
                else
                {
                    // 構成不可能なら0
                    if (num[e.To] + num[d] != S[e.Index])
                    {
                        Console.WriteLine(0);
                        return;
                    }
                }
            }
        }

        // rMinは1未満のみ考える
        long rMin = 1;

        long bMin = int.MaxValue;

        for (int i = 0; i < N; i++)
        {
            if (Dist[i] % 2 == 0)
            {
                rMin = Math.Min(rMin, num[i]);
            }
            else
            {
                bMin = Math.Min(bMin, num[i]);
            }
        }
        long ans = bMin - (1 - rMin);

        Console.WriteLine(Math.Max(0, ans));
    }
    void Type2()
    {
        // 2部グラフじゃない

        // 奇数長の閉路からすべての値が決まる
        // すべて正整数か? 1:0

        var num = new long[N];
        for (int i = 0; i < N; i++)
        {
            num[i] = long.MaxValue;
        }

        // num[0] = 0として適当に構成
        // 奇数回、偶数回両方で行ける頂点を見つける
        // num[0]を増やす 距離が偶数 増える　奇数 減る
        // 
        var dist = new int[N];
        for (int i = 0; i < N; i++)
        {
            dist[i] = -1;
        }

        var q = new Queue<int>();
        num[0] = 0;
        dist[0] = 0;
        q.Enqueue(0);

        long zero = long.MinValue;

        while (q.Count > 0)
        {
            var d = q.Dequeue();

            foreach (var e in Edges[d])
            {

                if (num[e.To] == long.MaxValue)
                {
                    num[e.To] = S[e.Index] - num[d];
                    dist[e.To] = dist[d] + 1;
                    q.Enqueue(e.To);
                }
                else
                {
                    if (dist[e.To] % 2 == (dist[d] + 1) % 2)
                    {
                        if (num[e.To] + num[d] != S[e.Index])
                        {
                            Console.WriteLine(0);
                            return;
                        }
                    }
                    else
                    {
                        if (dist[e.To] % 2 == 0)
                        {
                            // nun[0] を増やすと num[e.to]が増える S[e.index] - num[d]が減る
                            zero = ((S[e.Index] - num[d]) - num[e.To]) / 2;
                        }
                        else
                        {
                            zero = (num[e.To] - (S[e.Index] - num[d])) / 2;
                        }
                        break;
                    }
                }
            }
            if (zero != long.MinValue)
            {
                break;
            }
        }
        var ans = new long[N];

        var q2 = new Queue<int>();
        for (int i = 0; i < N; i++)
        {
            ans[i] = long.MaxValue;
        }
        ans[0] = zero;
        q2.Enqueue(0);

        while (q2.Count > 0)
        {
            var d = q2.Dequeue();
            foreach (var e in Edges[d])
            {
                if (ans[e.To] == long.MaxValue)
                {
                    ans[e.To] = S[e.Index] - ans[d];
                    q2.Enqueue(e.To);
                }
                else
                {
                    if (ans[e.To] + ans[d] != S[e.Index])
                    {
                        Console.WriteLine(0);
                        return;
                    }
                }
            }
        }

        Console.WriteLine(ans.Any(l => l <= 0) ? 0 : 1);
    }
    bool Check()
    {
        Dist = new int[N];
        for (int i = 0; i < N; i++)
        {
            Dist[i] = -1;
        }

        var q = new Queue<int>();
        Dist[0] = 0;
        q.Enqueue(0);

        while (q.Count > 0)
        {
            var d = q.Dequeue();
            foreach (var edge in Edges[d])
            {
                if (Dist[edge.To] == -1)
                {
                    Dist[edge.To] = Dist[d] + 1;
                    q.Enqueue(edge.To);
                }
                else
                {
                    if (Dist[edge.To] % 2 != (Dist[d] + 1) % 2)
                    {
                        return false;
                    }
                }
            }
        }
        return true;
    }



    public static void Main(string[] args) => new Program().Solve();
}

struct Edge
{
    public int To, Index;
    public Edge(int t, int i)
    {
        To = t;
        Index = i;
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;
    class Scanner
    {
        private int _index;
        private string[] _line;
        const char separator = ' ';

        public Scanner()
        {
            _index = 0;
            _line = new string[0];
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(separator);
                _index = 0;
            }
            return _line[_index++];
        }
        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(separator);
            _index = _line.Length;
            return _line;
        }
        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
    }
}

Measured memory_bytes: 35476