use std::io;
use std::cmp;
use std::collections::BinaryHeap;
use std::collections::HashMap;
use std::collections::HashSet;
use std::f64::consts::PI;
use std::cmp::Reverse;

fn read_line() -> String {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).ok();
    buf
}


fn main() {
    let line: Vec<usize> = read_line().split_whitespace().map(|s| s.parse().unwrap()).collect();
    let n = line[0];
    let m = line[1];
    let mut g = vec![Vec::new(); n];
    let mut e = Vec::new();
    for i in 0..m {
        let line: Vec<usize> = read_line().split_whitespace().map(|s| s.parse().unwrap()).collect();
        let a = line[0] - 1;
        let b = line[1] - 1;
        let c = line[2] as i64;

        g[a].push((b, i));
        g[b].push((a, i));
        e.push(c)
    }

    let mut used = vec![false; m+1];
    for i in 0..n {
        let mut que = BinaryHeap::new();
        que.push((0 as i64, i, m));
        let mut memo = vec![n; n];
        let mut cost = vec![1_000_010; n];
        while !que.is_empty() {
            let (cur, x, ei) = que.pop().unwrap();
            if cost[x] < -cur {
                continue;
            }
            used[ei] = true;
            if cost[x] == -cur {
                continue;
            }
            cost[x] = -cur;

            for i in 0..g[x].len() {
                let (nxt, ei) = g[x][i];
                que.push((cur - e[ei], nxt, ei));
            }
        }
    }
    let ans = used.iter().fold(0, |acc, val| if !*val { acc + 1 } else { acc });

    println!("{}", ans);
}
