#include <bits/stdc++.h>
using namespace std;
const long long MOD = (long long)(1e9 + 7);
const long long INF = (long long)(1e13 + 7);
const double EPS = 1e-14;
const double PI = acos(-1);
long long CEIL(long long a, long long b) {
  return (a >= 0 ? (a + (b - 1)) / b : (a - (b - 1)) / b);
}
long long mod(long long a, long long b) {
  return a >= 0 ? a % b : a - (b * CEIL(a, b));
}
long long bpm(long long a, long long b) {
  long long res = 1;
  for (a %= MOD; b; a = a * a % MOD, b >>= 1)
    if (b & 1) res = res * a % MOD;
  return res;
}
long long shortest_path[100][100];
long long V;
void warshall_floyd() {
  for (long long k = 0; k < V; k++) {
    shortest_path[k][k] = 0;
  }
  for (long long k = 0; k < V; k++) {
    for (long long i = 0; i < V; i++) {
      for (long long j = 0; j < V; j++) {
        shortest_path[i][j] =
            min(shortest_path[i][j], shortest_path[i][k] + shortest_path[k][j]);
      }
    }
  }
};
bool check[100][100];
vector<vector<pair<long long, long long>>> graph(100);
vector<bool> already(100, true);
long long first;
long long dfs(long long now, long long dis) {
  already[now] = false;
  long long p = 0;
  for (auto &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;
      }
      if (dfs(i.first, dis + i.second))
        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) {
    long long N, M;
    cin >> N >> M;
    for (long long i = 0; i < (long long)(N); i++) {
      for (long long j = 0; j < (long long)(N); j++) {
        shortest_path[i][j] = INF;
        check[i][j] = false;
        if (i == j) check[i][i] = true;
      }
    }
    for (long long _ = 0; _ < (long long)(M); _++) {
      long long 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();
    for (long long i = 0; i < (long long)(N); i++) {
      first = i;
      dfs(i, 0);
    }
    long long ans = 0;
    for (long long i = 0; i < (long long)(N); i++) {
      for (auto &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;
}
