#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <functional>
#include <queue>
#include <stack>
#include <string>
#include <utility>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <cassert>
#include <cinttypes>
#include <random>

using namespace std;

#if defined(_MSC_VER)
#pragma warning(disable: 4996) // VSでscanfを使う．
#endif

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  types                                                                                                                        /
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
typedef unsigned int uint;
typedef long long int ll;
typedef unsigned long long int ull;

typedef pair<ll, ll> P;
inline P operator+(const P& p1, const P& p2) { return P(p1.first + p2.first, p1.second + p2.second); }
inline P operator-(const P& p1, const P& p2) { return P(p1.first - p2.first, p1.second - p2.second); }
inline P operator*(const P& p1, const P& p2) { return P(p1.first * p2.first, p1.second * p2.second); }
inline P operator/(const P& p1, const P& p2) { return P(p1.first / p2.first, p1.second / p2.second); }

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  IO                                                                                                                        /
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Print(const int& x)    { printf("%d\n", x);         }
void Print(const uint& x)   { printf("%u\n", x);         }
void Print(const ll& x)     { printf("%lld\n", x);       }
void Print(const ull& x)    { printf("%llu\n", x);       }
void Print(const float& x)  { printf("%.15f\n", x);      }
void Print(const double& x) { printf("%.15f\n", x);      }
void Print(const string& x) { printf("%s\n", x.c_str()); }
void Print(const char& x)   { printf("%c\n", x);         }
template<class ...T> void Print(const int& x, const T& ...args)    { printf("%d ", x);         Print(args...); }
template<class ...T> void Print(const uint& x, const T& ...args)   { printf("%u ", x);         Print(args...); }
template<class ...T> void Print(const ll& x, const T& ...args)     { printf("%lld ", x);       Print(args...); }
template<class ...T> void Print(const ull& x, const T& ...args)    { printf("%llu ", x);       Print(args...); }
template<class ...T> void Print(const float& x, const T& ...args)  { printf("%.15f ", x);      Print(args...); }
template<class ...T> void Print(const double& x, const T& ...args) { printf("%.15f ", x);      Print(args...); }
template<class ...T> void Print(const string& x, const T& ...args) { printf("%s ", x.c_str()); Print(args...); }
template<class ...T> void Print(const char& x, const T& ...args)   { printf("%c ", x);         Print(args...); }

void Read(int& x)    { scanf("%d", &x);        }
void Read(uint& x)   { scanf("%u", &x);        }
void Read(ll& x)     { scanf("%lld", &x);      }
void Read(ull& x)    { scanf("%llu", &x);      }
void Read(float& x)  { scanf("%f", &x);        }
void Read(double& x) { scanf("%lf", &x);       }
void Read(string& x) { cin >> x;               }
void Read(char& x)   { scanf("%c", &x);        }
template<class ...T> void Read(int& x, T& ...args)    { scanf("%d", &x);        Read(args...); }
template<class ...T> void Read(uint& x, T& ...args)   { scanf("%u", &x);        Read(args...); }
template<class ...T> void Read(ll& x, T& ...args)     { scanf("%lld", &x);      Read(args...); }
template<class ...T> void Read(ull& x, T& ...args)    { scanf("%llu", &x);      Read(args...); }
template<class ...T> void Read(float& x, T& ...args)  { scanf("%f", &x);        Read(args...); }
template<class ...T> void Read(double& x, T& ...args) { scanf("%lf", &x);       Read(args...); }
template<class ...T> void Read(string& x, T& ...args) { cin >> x;               Read(args...); }
template<class ...T> void Read(char& x, T& ...args)   { scanf("%c", &x);        Read(args...); }

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Utility                                                                                                                   /
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
template<typename T> int len(T elem) { return (int)elem.size(); }

// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  main                                                                                                                      /
// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

const int INF = 1e8;

struct Edge {
  int id;
  int to;
  int cost;
  
  Edge() = default;
  Edge(int id, int to, int cost): id(id), to(to), cost(cost) { }

};

int main() {
  int n, m;
  Read(n, m);

  vector<Edge> G[101];

  for (int i = 0; i < m; i++) {
    int a, b, c;
    Read(a, b, c);
    a--;
    b--;

    G[a].push_back(Edge(i, b, c));
    G[b].push_back(Edge(i, a, c));
  }

  bool used[1001] = { };

  for (int s = 0; s < n; s++) {
    for (int t = s + 1; t < n; t++) {
      
      int cost[101];
      P path[101];
      for (int i = 0; i < 101; i++) {
        cost[i] = INF;
        path[i] = P(-1, -1);
      }

      priority_queue<P, vector<P>, greater<P>> que;

      que.push(P(0, s));
      while (!que.empty()) {
        P q = que.top();
        que.pop();
        
        int c = q.first;
        int v = q.second;
        
        for (auto edge : G[v]) {
          int u = edge.to;
          if (c + edge.cost < cost[edge.to]) {
            cost[u] = c + edge.cost;
            que.push(P(cost[u], u));
            path[u] = P(v, edge.id);
          }
        }
      }

      {
        P v = path[t];
        while (true) {
          used[v.second] = true;
          v = path[v.first];
          if (v.first == s) {
            break;
          }
        }
      }
    }
  }

  int ans = 0;
  for (int i = 0; i < m; i++) {
    if (!used[i]) {
      ans++;
    }
  }
  Print(ans);

  return 0;
}
/* */


Measured memory_bytes: 256