Problem:
Score : 400 points

Problem Statement

You are given an undirected connected weighted graph with N vertices and M edges that contains neither self-loops nor double edges.

The i-th (1≤i≤M) edge connects vertex a_i and vertex b_i with a distance of c_i.

Here, a self-loop is an edge where a_i = b_i (1≤i≤M), and double edges are two edges where (a_i,b_i)=(a_j,b_j) or (a_i,b_i)=(b_j,a_j) (1≤i<j≤M).

A connected graph is a graph where there is a path between every pair of different vertices.

Find the number of the edges that are not contained in any shortest path between any pair of different vertices.

Constraints

2≤N≤100

N-1≤M≤min(N(N-1)/2,1000)

1≤a_i,b_i≤N

1≤c_i≤1000

c_i is an integer.

The given graph contains neither self-loops nor double edges.

The given graph is connected.

Input

The input is given from Standard Input in the following format:

N M
a_1 b_1 c_1
a_2 b_2 c_2
:
a_M b_M c_M

Output

Print the number of the edges in the graph that are not contained in any shortest path between any pair of different vertices.

Sample Input 1

3 3
1 2 1
1 3 1
2 3 3

Sample Output 1

1

In the given graph, the shortest paths between all pairs of different vertices are as follows:

The shortest path from vertex 1 to vertex 2 is: vertex 1 → vertex 2, with the length of 1.

The shortest path from vertex 1 to vertex 3 is: vertex 1 → vertex 3, with the length of 1.

The shortest path from vertex 2 to vertex 1 is: vertex 2 → vertex 1, with the length of 1.

The shortest path from vertex 2 to vertex 3 is: vertex 2 → vertex 1 → vertex 3, with the length of 2.

The shortest path from vertex 3 to vertex 1 is: vertex 3 → vertex 1, with the length of 1.

The shortest path from vertex 3 to vertex 2 is: vertex 3 → vertex 1 → vertex 2, with the length of 2.

Thus, the only edge that is not contained in any shortest path, is the edge of length 3 connecting vertex 2 and vertex 3, hence the output should be 1.

Sample Input 2

3 2
1 2 1
2 3 1

Sample Output 2

0

Every edge is contained in some shortest path between some pair of different vertices.

Solution in C++14 (Clang 3.8.0) (judge verdict: Wrong Answer)

#include<algorithm>
#include<cmath>
#include<iomanip>
#include<iostream>
#include<map>
#include<numeric>
#include<queue>
#include<set>
#include<sstream>
#include<unordered_map>
#include<unordered_set>
#include<vector>
using uint = unsigned int;
using ll = long long;
enum : int { M = (int)1e9 + 7 };
enum : ll { MLL = (ll)1e18L + 9 };
using namespace std;
#ifdef LOCAL
#include"rprint2.hpp"
#include"debug_deque.hpp"
#define vector DebugDeque
#else
#define FUNC(name) template <ostream& out = cout, class... T> void name(T&&...){ }
FUNC(prints) FUNC(printe) FUNC(printw) FUNC(printew) FUNC(printb) FUNC(printd) FUNC(printde);
#endif
template <class S, class T>
struct Spair{
    S first;
    T second;
    Spair() = default;
    Spair(S aa, T bb){
        if(aa < bb){
            first = aa; second = bb;
        }else{
            first = bb; second = aa;
        }
    }
    // operator ll () const { return ((ll)first << 32) + second; }
    operator pair<S, T>() const { return {first, second}; }
    bool operator < (const Spair& s) const {
        return pair<S, T>(*this) < pair<S, T>(s);
    }
    bool operator == (const Spair& s) const {
        return pair<S, T>(*this) == pair<S, T>(s);
    }
    ostream& operator >> (ostream& out){
        return out << first << ' ' << second;
    }
};
namespace std{
    template <>
        struct hash<Spair<int, int>> {
            size_t operator () (const Spair<int, int>& sp){
                return ((ll)sp.first << 32) + sp.second;
            }
        };
}
unordered_set<Spair<int, int>> used;
struct Graph{
    struct Edge{
        int cost, from, dest;
        Edge(int cost, int dest): cost(cost), from(-1), dest(dest){ }
        Edge(int cost, int from, int dest): cost(cost), from(from), dest(dest){ }
        // bool operator < (const Edge& e) const { return cost < e.cost; }
        bool operator < (const Edge& e) const { return cost > e.cost; }
    };
    struct Node{
        vector<Edge> edges;
    };
    vector<Node> nodes;
    Graph(int num): nodes(num){ }
    void addEdge(int from, int dest, int cost = 1){
        nodes[from].edges.emplace_back(cost, from, dest);
        // prints(nodes[from].edges);
    }
    void addEdge2(int from, int dest, int cost = 1){
        addEdge(from, dest, cost);
        addEdge(dest, from, cost);
    }
    ll dijkstra(int start, int goal){
        priority_queue<Edge> pq;
        pq.emplace(0, start);
        vector<char> visited(nodes.size());
        ll len = 0;
        while(pq.size()){
            auto e = pq.top(); pq.pop();
            if(visited[e.dest]){ continue; }
            visited[e.dest] = true;
            len += e.cost;
            if(e.from >= 0){
                used.emplace(e.from, e.dest);
            }
            if(e.dest == goal){
                return len;
            }
            for(auto& e : nodes[e.dest].edges){
                pq.push(e);
            }
        }
        return -1;
    }
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int n, m;
    cin >> n >> m;
    Graph g(n);
    for(int i = 0; i < m; i++){
        int a, b, c;
        cin >> a >> b >> c;
        a--; b--;
        g.addEdge2(a, b, c);
    }
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++){
            g.dijkstra(i, j);
        }
    }
    prints(used);
    cout << m - used.size() << '\n';
}