#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<tuple>
#include<set>
#include<functional>

template<class T>using p_queue = std::priority_queue<T, std::vector<T>, std::greater<>>;
int main()
{
	int N, M;
	std::cin >> N >> M;
	std::vector<std::map<int, int>> edge(N);
	std::set<std::pair<int, int>> set;
	for (int i{};i < M;++i)
	{
		int a, b, c;
		std::cin >> a >> b >> c;
		edge[a - 1][b - 1] = c;
		edge[b - 1][a - 1] = c;
		set.emplace(std::max(a - 1, b - 1), std::min(a - 1, b - 1));
	}

	for (int i{};i < N;++i)
	{
		std::vector<int> flag(N, 0);
		flag[i] = true;
		p_queue<std::tuple<int, int, int>> queue;
		for (auto const& p : edge[i])
		{
			queue.emplace(p.second, p.first);
		}
		while (queue.size())
		{
			auto top = queue.top();
			queue.pop();
			auto dis = std::get<0>(top);
			auto now = std::get<1>(top);
			auto from = std::get<2>(top);
			if (flag[now])
			{
				continue;
			}
			flag[now] = true;
			set.erase(std::make_pair(std::max(from, now), std::min(from, now)));
			for (auto const& p : edge[now])
			{
				queue.emplace(dis + p.second, p.first);
			}
		}
	}
	std::cout << set.size() << std::endl;
}