/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Kein Yukiyoshi
 */

#include "bits/stdc++.h"
#define int long long
#define rep(i, n)           for (int i = 0; i < (int)(n); i++)
#define REP(i, a, b)        for (int i = (int)(a); i < (int)(b); i++)
#define FOR(i, a)           for (auto &i : a)
#define ALL(obj)            begin(obj), end(obj)
#define MAX(x)              *max_element(ALL(x))
#define MIN(x)              *min_element(ALL(x))
#define SUM(x)              accumulate(ALL(x), 0LL)
#define LOWER_BOUND(A, key) distance(A.begin(), lower_bound(ALL(A), key))
#define UPPER_BOUND(A, key) distance(A.begin(), upper_bound(ALL(A), key))

using namespace std;
const int MOD    = (int)(1e9 + 7);
const int INF    = (int)(1e13 + 7);
const double EPS = 1e-14;
const double PI  = acos(-1);

int CEIL(int a, int b) { return (a >= 0 ? (a + (b - 1)) / b : (a - (b - 1)) / b); } //ceil() for int
int mod(int a, int b) { return a >= 0 ? a % b : a - (b * CEIL(a, b)); }             //always return positive num
int bpm(int a, int b) {                                                             //return x^y in order(log(y))
  int res = 1;
  for (a %= MOD; b; a = a * a % MOD, b >>= 1)
    if (b & 1) res = res * a % MOD;
  return res;
}

#define MAX_V 100                //change if you need
int shortest_path[MAX_V][MAX_V]; //shortest_path[i][j] = cost(i→j) or INF
int V;                           //num of nodes
void warshall_floyd() {
  for (int k = 0; k < V; k++) {
    shortest_path[k][k] = 0;
  }
  for (int k = 0; k < V; k++) {
    for (int i = 0; i < V; i++) {
      for (int j = 0; j < V; j++) {
        shortest_path[i][j] = min(shortest_path[i][j], shortest_path[i][k] + shortest_path[k][j]);
      }
    }
  }
};
bool check[MAX_V][MAX_V];
vector<vector<pair<int, int>>> graph(MAX_V);
vector<bool> already(MAX_V, true);
int first;
int dfs(int now, int dis) {
  already[now] = false;
  int p        = 0;
  FOR(i, graph[now]) {
    if (already[i.first]) {
      if (dis + i.second == shortest_path[first][i.first]) {
        p++;
        check[now][i.first] = check[i.first][now] = true;
        p += dfs(i.first, dis + i.second);
      }
    }
  }
  already[now] = true;
  return p;
}

class DCandidatesOfNoShortestPaths {
public:
  static void solve(istream &cin, ostream &cout) {
    int N, M;
    cin >> N >> M;
    rep(i, N) {
      rep(j, N) {
        shortest_path[i][j] = INF;
        check[i][j]         = false;
        if (i == j) check[i][i] = true;
      }
    }
    rep(_, M) {
      int a, b, c;
      cin >> a >> b >> c;
      shortest_path[a - 1][b - 1] = c;
      shortest_path[b - 1][a - 1] = c;
      graph[a - 1].emplace_back(b - 1, c);
      graph[b - 1].emplace_back(a - 1, c);
    }
    V = N;
    warshall_floyd();
    rep(i, N) {
      first = i;
      dfs(i, 0);
    }
    int ans = 0;
    rep(i, N) {
      FOR(j, graph[i]) {
        if (check[i][j.first] == false) ans++;
      }
    }
    cout << ans / 2 << endl;
  }
};


signed main() {
  cin.tie(0);
  cout.tie(0);
  ios_base::sync_with_stdio(false);
  cout<<fixed<<setprecision(15);
  DCandidatesOfNoShortestPaths solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  solver.solve(in, out);
  return 0;
}


Measured memory_bytes: 3680