#include <bits/stdc++.h>
using namespace std;
const long long INF = 1e+18 + 1;
const long long MOD = 1000000007LL;
string abc = "abcdefghijklmnopqrstuvwxyz";
string ABC = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
struct Edge {
  long long to;
  long long cost;
};
using Graph = vector<vector<Edge>>;
void dijkstra(const Graph &G, long long s, vector<long long> &dis,
              vector<long long> &prev) {
  long long N = G.size();
  dis.resize(N, INF);
  prev.resize(N, -1);
  priority_queue<pair<long long, long long>, vector<pair<long long, long long>>,
                 greater<pair<long long, long long>>>
      pq;
  dis[s] = 0;
  pq.emplace(dis[s], s);
  while (!pq.empty()) {
    pair<long long, long long> p = pq.top();
    pq.pop();
    long long v = p.second;
    if (dis[v] < p.first) {
      continue;
    }
    for (auto &e : G[v]) {
      if (dis[e.to] > dis[v] + e.cost) {
        dis[e.to] = dis[v] + e.cost;
        prev[e.to] = v;
        pq.emplace(dis[e.to], e.to);
      }
    }
  }
}
int main() {
  long long n, m;
  cin >> n >> m;
  vector<vector<bool>> data(n, vector<bool>(n, false));
  vector<vector<Edge>> G;
  for (long long i = 0; i < (long long)(m); i++) {
    long long a, b, c;
    cin >> a >> b >> c;
    a--;
    b--;
    data[a][b] = true;
    data[b][a] = true;
    Edge e;
    e.to = b;
    e.cost = c;
    G[a].push_back(e);
  }
  for (long long i = 0; i < (long long)(n); i++) {
    vector<long long> prev;
    vector<long long> dis;
    dijkstra(G, i, dis, prev);
    for (long long j = 0; j < (long long)(prev.size() - 1); j++) {
      data[prev[j]][prev[j + 1]] = false;
      data[prev[j + 1]][prev[j]] = false;
    }
  }
  long long count = 0;
  for (long long i = 0; i < (long long)(n); i++) {
    for (long long j = 0; j < (long long)(n); j++) {
      if (data[i][j]) count++;
    }
  }
  cout << count / 2 << endl;
}
