using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication14
{
    enum qResult 
    {
        REJECT,
        ENQUEUED,
        HIT
    }

    class Node 
    {
        public Dictionary<int, int> fLen = new Dictionary<int, int>();
        public HashSet<int> Checked = new HashSet<int>();
    }

    class LocalQueue 
    {
        Queue<int> nodeNum = new Queue<int>();
        Queue<int> totalLen = new Queue<int>();
        Queue<HashSet<int>> History = new Queue<HashSet<int>>();
        int targetNum;
        int th;
        
        private void ClrQueue()
        {
            nodeNum.Clear();
            totalLen.Clear();
            History.Clear();
        }

        public LocalQueue(int target, int len, ref Node[] nodeAry, int me)
        {
            targetNum = target;
            th = len;
            foreach(var p in nodeAry[me].fLen.Keys)
            {
                if (p == target) continue;
                nodeNum.Enqueue(p);
                totalLen.Enqueue(nodeAry[me].fLen[p]);
                HashSet<int> h = new HashSet<int>();
                h.Add(me);
                History.Enqueue(h);
            }
        }

        public qResult Enqueue(int nNum, int tLen, HashSet<int> h)
        {
            //探索済みは捨てる
            if (h.Contains(nNum)) return qResult.REJECT;

            //現時点でthより距離が大ならば捨ててよい
            if (tLen >= th) return qResult.REJECT;

            //ターゲットに到達かつ距離が短い場合はHITを返す
            //これ以上の探索は不要なのでQueueを全部破棄する
            if (nNum == targetNum)
            {
                ClrQueue();
                return qResult.HIT;
            }

            //ターゲットに到達してないのでEnqueueして
            //次の階層を探す様にする
            nodeNum.Enqueue(nNum);
            totalLen.Enqueue(tLen);
            HashSet<int> newH = new HashSet<int>(h);
            newH.Add(nNum);
            History.Enqueue(newH);
            return qResult.ENQUEUED;
        }

        public bool Dequeue(out int nNum, out int tLen, out HashSet<int> h) 
        {
            //もしQueue枯渇ならばfalseを返す
            nNum = -1; tLen = -1; h = null;
            if (nodeNum.Count == 0) return false;

            //Dequeueする
            nNum = nodeNum.Dequeue();
            tLen = totalLen.Dequeue();
            h = History.Dequeue();
            return true;
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            string[] msg = Console.ReadLine().Split(' ');
            int N = int.Parse(msg[0]);
            int M = int.Parse(msg[1]);
            Node[] nodeAry = new Node[N];
            for (int i = 0; i < N; i++) nodeAry[i] = new Node();

            for (int i = 0; i < M; i++) 
            {
                msg = Console.ReadLine().Split(' ');
                int ai = int.Parse(msg[0]) - 1;
                int bi = int.Parse(msg[1]) - 1;
                int ci = int.Parse(msg[2]);
                nodeAry[ai].fLen.Add(bi, ci);
                nodeAry[bi].fLen.Add(ai, ci);
            }

            int count = 0;
            for (int i = 0; i < N; i++)
            {
                //Nodeを取得
                foreach (var f in nodeAry[i].fLen.Keys) 
                {
                    //既に確認済みの組み合わせは省略(多重カウントを弾く為)
//                    if (nodeAry[i].Checked.Contains(f) || nodeAry[f].Checked.Contains(i)) continue;

                    //取得Nodeとfriendな関係を持つNodeへの
                    //迂回リンクより最短のリンクを手繰る
                    //もし直リンクより迂回リンクの方が距離が短いならばカウンタをインクリメント
                    //(幅優先検索で距離を算出するが、途中で直リンクより短距離が見えた時点で
                    // 検索を中断して良いはず＆直リンクより遠距離確定時点でQueueから捨てて良いはず)
                    LocalQueue lq = new LocalQueue(f, nodeAry[i].fLen[f],ref nodeAry, i);
                    int nNum; int tLen; HashSet<int> his;
                    while (lq.Dequeue(out nNum, out tLen, out his))
                    {
                        foreach (var nf in nodeAry[nNum].fLen.Keys)
                        {
                            if (lq.Enqueue(nf, tLen + nodeAry[nNum].fLen[nf], his) == qResult.HIT)
                            {
                                count++;
                                nodeAry[i].Checked.Add(nf);
                                break;
                            }
                        }
                    }
                }
            }
            Console.WriteLine((count / 2).ToString());
            Console.ReadLine();
        }
    }
}


Measured memory_bytes: 8184