#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void _err(std::ostream& cerr, istream_iterator<string> it) { cerr << endl; }
template <typename T, typename... Args>
void _err(std::ostream& cerr, istream_iterator<string> it, T a, Args... args) {
  cerr << *it << " = " << a << "  ";
  _err(cerr, ++it, args...);
}
const double pi = 2 * acos(.0);
const int inf = 0x3f3f3f3f;
const ll mod = (ll)(1e9) + 7;
const double eps = 1e-10;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T& val) {
  std::fill((T*)array, (T*)(array + N), val);
}
template <typename T>
ostream& operator<<(ostream& os, const vector<T> V) {
  for (auto v : V) os << v << " ";
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const set<T> V) {
  for (auto v : V) os << v << " ";
  return os;
}
template <typename T>
ostream& operator<<(ostream& os, const deque<T> V) {
  for (auto v : V) os << v << " ";
  return os;
}
template <class T>
bool Chmax(T& a, const T& b) {
  if (a < b) {
    a = b;
    return 1;
  }
  return 0;
}
template <class T>
bool Chmin(T& a, const T& b) {
  if (b <= a) {
    a = b;
    return 1;
  }
  return 0;
}
class DCandidatesOfNoShortestPaths {
 public:
  int N, M;
  void solve(std::istream& cin, std::ostream& cout, std::ostream& cerr) {
    vector<vector<int>> dist(101, vector<int>(101, inf));
    vector<vector<int>> edge(101, vector<int>(101, 0));
    cin >> N >> M;
    ll ans = 0;
    for (__typeof(M) i = 0, _len = (M); i < (_len); i += 1) {
      int a, b, c;
      cin >> a >> b >> c;
      a--, b--;
      dist[a][b] = c;
      edge[a][b] = 1;
      dist[b][a] = c;
    }
    for (__typeof(N) i = 0, _len = (N); i < (_len); i += 1) dist[i][i] = 0;
    auto dist_min = dist;
    for (__typeof(N) k = 0, _len = (N); k < (_len); k += 1)
      for (__typeof(N) i = 0, _len = (N); i < (_len); i += 1)
        for (__typeof(N) j = 0, _len = (N); j < (_len); j += 1)
          Chmin(dist_min[i][j], dist_min[i][k] + dist_min[k][j]);
    for (__typeof(N) i = 0, _len = (N); i < (_len); i += 1)
      for (__typeof(N) j = 0, _len = (N); j < (_len); j += 1)
        if (edge[i][j]) {
          for (__typeof(N) k = 0, _len = (N); k < (_len); k += 1)
            if (k != i && k != j &&
                dist[i][j] >= dist_min[i][k] + dist_min[k][j]) {
              ans++;
              break;
            }
        }
    cout << ans << endl;
  }
};
int main() {
  DCandidatesOfNoShortestPaths solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  std::ostringstream err;
  in.tie(0);
  ios::sync_with_stdio(0);
  solver.solve(in, out, err);
  return 0;
}
