#include <bits/stdc++.h>
 
#ifndef LOCAL_
#define fprintf if( false ) fprintf
#endif // LOCAL_
#define dumpl(x1) fprintf(stderr, "#%s.%d (%s) = (%ld)\n", __func__, __LINE__, #x1, x1);
#define dumpll(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%ld, %ld)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define dumplll(x1, x2, x3) fprintf(stderr, "#%s.%d (%s, %s, %s) = (%ld, %ld, %ld)\n", __func__, __LINE__, #x1, #x2, #x3, x1, x2, x3);
#define dumpd(x1) fprintf(stderr, "#%s.%d (%s) = (%lf)\n", __func__, __LINE__, #x1, x1);
#define dumpdd(x1, x2) fprintf(stderr, "#%s.%d (%s, %s) = (%lf, %lf)\n", __func__, __LINE__, #x1, #x2, x1, x2);
#define loop for(;;)
 
struct S002 {
  int n;
  S002& operator > (long& x) {
    n = x;
    return *this;
  }
  S002& operator > (long&& x) {
    n = x;
    return *this;
  }
  S002& operator >= (long& x) {
    if( scanf("%ld", &x) <= 0 ) exit(0);
    return *this;
  }
  S002& operator >= (double& x) {
    if( scanf("%lf", &x) <= 0 ) exit(0);
    return *this;
  }
  S002& operator >= (std::string& s) {
    if( not (std::cin >> s) ) exit(0);
    return *this;
  }
  template<typename a>
  S002& operator >= (std::vector<a>& v) {
    v.resize(n);
    for(long i = 0; i < n; ++i) {
      *this >= v[i];
    }
    return *this;
  }
  template<typename a, std::size_t s>
  S002& operator >= (std::array<a, s>& x) {
    for(long i = 0; i < (long)s; ++i) {
      *this >= x[i];
    }
    return *this;
  }
};

template<typename a>
struct S005 {
  typedef a e;
  std::vector<std::vector<a>> xs;
  const std::vector<a>& ys;
  long n;
  S005(const std::vector<a>& ys_, long n_) : ys(ys_), n(n_) {
    xs.resize(n);
    for(a x : ys) {
      a y = x;
      xs[x.s].push_back(y);
    }
  }
  const std::vector<a>& operator [] (long i) const {
    return xs[i];
  }
  long v() const {
    return n;
  }
  const std::vector<a>& es() const {
    return ys;
  }
};

template<typename a>
struct S031 {
  typedef a wt;
  S031() : s(-1), d(-1) {}
  S031(long s_, long d_, a w_) : s(s_), d(d_), w(w_) {}
  long s, d;
  a w;
};

template<typename e>
struct S032 {
  struct X {
    std::vector<std::vector<typename e::wt>> x;
    X(long v) {
      x.resize(v);
      for(long i = 0; i < v; ++i) {
        x[i].resize(v);
      }
    }
    std::vector<typename e::wt>& operator[](long i) {
      return x[i];
    }
  };
  X operator()(const std::vector<e>& edges, long v) {
    X res(v);
    for(long i = 0; i < v; ++i) {
      for(long j = 0; j < v; ++j) {
        res[i][j] = (1 << 29);
      }
      res[i][i] = 0;
    }
    for(e edge : edges) {
      res[edge.s][edge.d] = edge.w;
    }
    for(long k = 0; k < v; ++k) {
      for(long i = 0; i < v; ++i) {
        for(long j = 0; j < v; ++j) {
          res[i][j] = std::min(res[i][j], res[i][k] + res[k][j]);
        }
      }
    }
    return res;
  }
};

struct Solver {
  typedef S031<long> Edge;
  long n, m;
  std::vector<std::array<long, 3>> xs;
  Solver() {
    S002 reader;
    reader >= n >= m >m>= xs;
  }
  void solve() {
    std::vector<Edge> edges;
    for(auto x : xs) {
      edges.push_back(Edge(x[0]-1, x[1]-1, x[2]));
      edges.push_back(Edge(x[1]-1, x[0]-1, x[2]));
    }
    S032<Edge> wf;
    auto s = wf(edges, n);
    long res = 0;
    for(Edge edge : edges) {
      if( edge.s > edge.d ) continue;
      long t = 0;
      for(long i = 0; i < n; ++i) {
        long x = edge.s;
        long y = edge.d;
        long z = i;
        if( edge.w + s[y][z] == s[x][z] ) t += 1;
      }
      if( t != 0 ) res += 1;
    }
    printf("%ld\n", m - res);
  }
};

int main() {
  loop std::unique_ptr<Solver>(new Solver())->solve();
  return 0;
}

Measured memory_bytes: 384