#include<iostream>
#include<string>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<list>
#include<iomanip>
#include<vector>
#include<functional>
#include<algorithm>
#include<cstdio>
#include<unordered_map>
using namespace std;
//---------------------------------------------------
//ライブラリゾーン！！！！
#define int long long
#define str string
#define rep(i,j) for(int i=0;i<(int)(j);i++)
typedef long long ll;
typedef long double ld;
const ll inf = 999999999999999999;
struct P {
	ll pos, cost;
};
bool operator<(P a, P b) { return a.cost < b.cost; }
bool operator>(P a, P b) { return a.cost > b.cost; }
struct B {//隣接リスト表現
	ll to, cost;
};
struct S {//辺の情報を入れる変数
	int from, to, cost;
};
ll gcm(ll i, ll j) {//最大公約数
	if (i > j) swap(i, j);
	if (i == 0) return j;
	return gcm(j%i, i);
}
//---------------------------------------------------
//+++++++++++++++++++++++++++++++++++++++++++++++++++
int n, m;
int a[101][101];
S b[5000];
signed main() {
	cin >> n >> m;
	rep(i, 101)
		rep(j, 101)
		a[i][j] = inf;
	for (int i = 0; i <= 101; i++)
		a[i][i] = 0;
	for (int i = 0; i < m; i++) {
		cin >> b[i].from >> b[i].to >> b[i].cost;
		a[b[i].from][b[i].to] = b[i].cost;
	}
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j <= n; j++) {
			for (int k = 1; k <= n; k++) {
				a[i][j] = min(a[i][j], a[i][k] + a[k][j]);
				a[j][i] = a[i][j];
			}
		}
	}
	int sum = 0;
	for (int i = 0; i < m; i++) {
		bool l = 1;
		for (int j = 1; j <= n; j++) {
			if (a[b[i].from][j] + b[i].cost == a[b[i].to][j])
				l = 0;
			if (a[b[i].to] + b[i].cost == a[b[i].from][j])
				l = 0;
		}
		if (l)
			sum++;
	}
	cout << sum << endl;
	getchar(); getchar();
}