#include <bits/stdc++.h>
using namespace std;

#define pb         push_back

typedef long long ll;
const ll INF = 1000000000ll;
const ll MOD = 1000000007ll;
const double EPS = 1e-8;

int n, m;
int adj[200][200];
bool useE[200][200];
bool used[200];
int prev[200];
int d[200];

void dijkstra(int s){
	fill(d, d + n, INF);
	fill(used, used + n, false);
	for(int i=0; i<n; i++){
		prev[i] = -1;
	}
	d[s] = 0;

	while(true){
		int v = -1;
		for(int u=0; u < n; u++){
			if(!used[u] && (v == -1 || d[u] < d[v])) v = u;
		}

		if(v == -1) break;
		used[v] = true;

		for(int u = 0; u < n; u++){
			if(d[u] > d[v] + adj[v][u]){
				d[u] = d[v] + adj[v][u];
				prev[u] = v;
			}
		}
	}
}

vector<int> get_path(int t, int s){
	vector<int> path;
	for(; t != -1; t = prev[t]){
		path.push_back(t);
	}
	reverse(path.begin(), path.end());

	for(int i=0; i < path.size()-1; i++){
		useE[path[i]][path[i+1]] = useE[path[i+1]][path[i]] = true;
	}
	return path;
}

int main(void) {
	//ios_base::sync_with_stdio(false);
	//cin.tie(0);
	
	cin >> n >> m;
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			adj[i][j] = adj[j][i] = INF;
		}
	}

	for(int i=0; i<m; i++){
		int a, b, c;
		cin >> a >> b >> c;
		a--;
		b--;
		adj[a][b] = adj[b][a] = c;
	}


	for(int i=1; i<n; i++){
		dijkstra(i);
		for(int j=0; j<n; j++){
			if(i == j) continue;
			get_path(j, i);
		}
	}

	ll ans = 0;
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			if(adj[i][j] != INF && useE[i][j] == false) ans++;
		}
	}
	/*
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			if(adj[i][j] != INF){
				printf("%d ", adj[i][j]);
			}else{
				printf("# ");
			}
		}
		puts("");
	}
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			printf("%d ", useE[i][j]);
		}
		puts("");
	}
	*/

	cout << ans/2 << endl;
	
	return 0;
}
