#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>
#include <sstream>
#include <algorithm>

using namespace std;

#define	numberof(a)	(sizeof(a) / sizeof(a[0]))
#define	INF		(1000000)
#define Rep(i,n) for(int i = 0; i < (n); i++ )

//clear memory
#define CLR(a) memset((a), 0 ,sizeof(a))

//debug
#define dump(x)  cout << #x << " = " << (x) << endl;
#define debug(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;
#define	show(x)	 copy( (x).begin(), (x).end(), ostream_iterator<int>(cout, ",") );	// container<int>を全て表示

using namespace std;

typedef long long ll;

//constant
//--------------------------------------------
const double EPS = 1e-10;
const double PI = acos(-1.0);


map<ll, ll> prime_factor2(ll N)
{
	map<ll, ll> ret;

	for (ll i = 2; i * i <= N; ++i ) {
		while ( N % i == 0 ) {
			ret[i]++;
			N /= i;
		}
	}

	if (N != 1) ret[N]++;
	return ret;
}

int main()
{
	ll N, M;
	vector<ll> a(M, 0);
	vector<ll> b(M, 0);
	vector<ll> c(M, 0);
	ll ans = 0;

	cin >> N >> M;
	vector< vector<ll> > dist(N, vector<ll>(N, INF));

	Rep(i, M) {
		cin >> a[i] >> b[i] >> c[i];
		a[i]--;
		b[i]--;
	}

	for (ll i = 0; i < N; ++i) {
		for (ll j = 0; j < N; ++j) {
			if (i == j) dist[i][j] = 0;
			else dist[i][j] = INF;
		}
	}

	for (ll i = 0; i < M; ++i) {
		dist[a[i]][b[i]] = min(dist[a[i]][b[i]], c[i]);
		dist[b[i]][a[i]] = min(dist[b[i]][a[i]], c[i]);
	}

	for (ll i = 0; i < N; ++i) {
		for (ll j = 0; j < N; ++j) {
			for (ll k = 0; k < N; ++k) {
				dist[i][j] = min( dist[i][j], dist[i][k] + dist[k][j]);
			}
		}
	}

	ans = M;
	for (ll i = 0; i < M; ++i) {
		bool found = false;

		for (ll j = 0; j < N; ++j) {
			if (dist[j][b[i]] == dist[j][a[i]] + c[i]) found = true;
		}
		
		if (found) ans--;
	}
		
	cout << ans << endl;

	return 0;
}
