#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vi = vector<int>;
using vvi = vector<vi>;
using vl = vector<ll>;
using vvl = vector<vl>;
using P = pair<int, int>;
using PL = pair<ll, ll>;
using vp = vector<P>;
using vpl = vector<PL>;
constexpr const int INF = 1 << 30, MOD = 1000000007;
constexpr const ll LINF = 1ll << 60;
void YES(int n) { cout << ((n) ? "YES" : "NO") << '\n'; }
void Yes(int n) { cout << ((n) ? "Yes" : "No") << '\n'; }
void Poss(int n) { cout << ((n) ? "Possible" : "Impossible") << '\n'; }
struct osd {
  template <class T>
  osd& operator<(const T& t) {
    return *this;
  }
  template <class T>
  osd& operator<<(const T& t) {
    return *this;
  }
};
osd cer_;
template <class... T>
void _print(osd& a, T&&... t) {}
template <class T>
ostream& operator<(ostream& o, const T& t) {
  return o << t;
}
template <class T>
istream& operator>(istream& i, T& t) {
  return i >> t;
}
void _print(ostream& s) {}
template <class T, class... U>
void _print(ostream& s, T&& t, U&&... u) {
  s < t < (sizeof...(u) ? ' ' : '\n');
  _print(s, u...);
}
template <class... T>
void print(T&&... t) {
  _print(cout, t...);
}
template <class... T>
void dprint(T&&... t) {
  _print(cer_, t...);
}
template <class T>
void chmax(T& a, const T& b) {
  if (a < b) a = b;
}
template <class T>
void chmin(T& a, const T& b) {
  if (a > b) a = b;
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  for (auto&& i : v) o < i < ' ';
  return o;
}
template <class T>
istream& operator>>(istream& i, vector<T>& v) {
  for (T& j : v) i > j;
  return i;
}
template <class T, class U>
ostream& operator<<(ostream& o, const pair<T, U>& p) {
  return o < p.first < ' ' < p.second;
}
template <class T, class U>
istream& operator>>(istream& i, pair<T, U>& p) {
  return i > p.first > p.second;
}
template <class T>
ostream& operator<<(ostream& o, const set<T>& v) {
  for (auto&& i : v) o < i < ' ';
  return o;
}
template <class T>
vector<T>& operator<<(vector<T>& v, const T& t) {
  v.push_back(t);
  return v;
}
template <class T>
queue<T>& operator<<(queue<T>& q, const T& t) {
  q.push(t);
  return q;
}
template <class T>
queue<T>& operator<<(T& t, queue<T>& q) {
  t = q.front();
  q.pop();
  return q;
}
template <class T>
deque<T>& operator>>(const T& t, deque<T>& q) {
  q.push_front(t);
  return q;
}
template <class T>
deque<T>& operator<<(T& t, deque<T>& q) {
  t = q.front();
  q.pop_front();
  return q;
}
template <class T>
deque<T>& operator<<(deque<T>& q, const T& t) {
  q.push_back(t);
  return q;
}
template <class T>
deque<T>& operator>>(deque<T>& q, T& t) {
  t = q.back(t);
  q.pop_back();
  return q;
}
template <class T>
stack<T>& operator<<(stack<T>& s, const T& t) {
  s.push(t);
  return s;
}
template <class T>
stack<T>& operator>>(stack<T>& s, T& t) {
  t = s.top();
  s.pop();
  return s;
}
int main() {
  cin.tie(0);
  ios::sync_with_stdio(0);
  int n, m;
  cin > n > m;
  vector<map<int, int>> edges(n);
  for (int i = 0, i_l = (m); i < i_l; ++i) {
    int a, b, c;
    cin > a > b > c;
    a--;
    b--;
    edges[a][b] = c;
    edges[b][a] = c;
  }
  int cnt = 0;
  for (int i = 0, i_l = (n); i < i_l; ++i) {
    for (auto&& e : edges[i]) {
      if (e.first < i) continue;
      dprint("test for:", i, '-', e.first, ':', e.second);
      for (int k = 0, k_l = (n); k < k_l; ++k) {
        if (k == i) continue;
        if (k == e.first) continue;
        auto ita = edges[k].find(i);
        if (ita == edges[k].end()) continue;
        auto itb = edges[k].find(e.first);
        if (itb == edges[k].end()) continue;
        dprint("test for:", i, '-', k, '-', e.first, ':',
               ita->second + itb->second);
        if (ita->second + itb->second < e.second) {
          cnt++;
          break;
        }
      }
    }
  }
  cout < cnt < '\n';
  return 0;
}
