#include <bits/stdc++.h>
using namespace std;
class Graph {
 public:
  struct Edge {
    long long to;
    long long distance;
    Edge(long long t, long long d) {
      to = t;
      distance = d;
    }
    bool operator<(const Edge &e) const { return distance > e.distance; }
    bool operator<=(const Edge &e) const { return distance >= e.distance; }
    bool operator>(const Edge &e) const { return distance < e.distance; }
    bool operator>=(const Edge &e) const { return distance <= e.distance; }
    bool operator==(const Edge &e) const { return distance == e.distance; }
  };
  vector<vector<long long>> adjacency_matrix;
  long long node;
  long long initial_value;
  vector<list<Edge>> edge;
  Graph(long long N) {
    setNode(N);
    initializeEdgeList();
  }
  Graph(long long N, long long init) {
    setNode(N);
    initializeEdgeList();
    setInitialValue(init);
  }
  void setNode(long long N) { node = N + 1; }
  void setInitialValue(long long init) { initial_value = init; }
  void initializeAdjacencyMatrix() {
    adjacency_matrix =
        vector<vector<long long>>(node, vector<long long>(node, initial_value));
  }
  void initializeAdjacencyMatrix(long long init) {
    setInitialValue(init);
    initializeAdjacencyMatrix();
  }
  void initializeEdgeList() { edge = vector<list<Edge>>(node); }
  void updateAdjacencyMatrix(long long from, long long to, long long distance) {
    adjacency_matrix[from][to] = distance;
  }
  void addEdge(long long from, long long to, long long distance) {
    edge[from].push_back({to, distance});
  }
  void runFloydWarshall() {
    for (int i = 0; i < node; i++) {
      for (int j = 0; j < node; j++) {
        for (int k = 0; k < node; k++) {
          adjacency_matrix[j][k] =
              min(adjacency_matrix[j][k],
                  adjacency_matrix[j][i] + adjacency_matrix[i][k]);
        }
      }
    }
  }
  vector<long long> runBellmanFord(long long from) {
    vector<long long> distance(node, initial_value);
    distance[from] = 0;
    for (long long i = 0; i < node - 1; i++) {
      for (long long j = 1; j < node; j++) {
        for (auto itr = edge[j].begin(); itr != edge[j].end(); itr++) {
          if (distance[itr->to] > distance[j] + itr->distance) {
            distance[itr->to] = distance[j] + itr->distance;
          }
        }
      }
    }
    for (long long i = 1; i < node; i++) {
      for (auto itr = edge[i].begin(); itr != edge[i].end(); itr++) {
        if (distance[itr->to] > distance[i] + itr->distance) {
          distance[0]--;
        }
      }
    }
    return distance;
  }
  vector<long long> runDijkstra(long long from) {
    vector<long long> distance(node, initial_value);
    priority_queue<Edge> queue;
    queue.push(Edge(from, 0));
    while (!queue.empty()) {
      long long d = queue.top().distance;
      long long to = queue.top().to;
      queue.pop();
      if (distance[to] == initial_value) {
        distance[to] = d;
        for (auto itr = edge[to].begin(); itr != edge[to].end(); itr++) {
          if (distance[itr->to] == initial_value) {
            queue.push({itr->to, itr->distance + d});
          }
        }
      }
    }
    return distance;
  }
  long long runPrim() {
    vector<bool> is_visited(node, false);
    long long cost = 0;
    priority_queue<Edge> queue;
    queue.push(Edge(1, 0));
    while (!queue.empty()) {
      long long distance = queue.top().distance;
      long long to = queue.top().to;
      queue.pop();
      if (!is_visited[to]) {
        cost += distance;
        is_visited[to] = true;
        for (auto itr = edge[to].begin(); itr != edge[to].end(); itr++) {
          queue.push({itr->to, itr->distance});
        }
      }
    }
    return cost;
  }
  long long runKruskal() {}
};
int main() {
  int N, M;
  cin >> N >> M;
  Graph g(N, 1000000000);
  int a, b, c;
  for (int i = 0; i < M; i++) {
    cin >> a >> b >> c;
    g.addEdge(a, b, c);
    g.addEdge(b, a, c);
  }
  g.initializeAdjacencyMatrix();
  for (int i = 1; i <= 3; i++) {
    g.adjacency_matrix[i] = g.runDijkstra(i);
  }
  int ans = 0;
  for (int i = 1; i <= N; i++) {
    for (auto itr = g.edge[i].begin(); itr != g.edge[i].end(); itr++) {
      bool is_used = false;
      for (int start = 1; start <= N; start++) {
        for (int to = 1; to <= N; to++) {
          int distance_via_edge = g.adjacency_matrix[start][i] + itr->distance +
                                  g.adjacency_matrix[itr->to][to];
          if (g.adjacency_matrix[start][to] == distance_via_edge) {
            is_used = true;
          }
        }
      }
      if (!is_used) {
        ans++;
      }
    }
  }
  cout << ans / 2 << endl;
}
