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 Lua (5.3.2) (judge verdict: Accepted)

-- heap
local Heap = {}
function Heap.new(upper_func)
    local self = setmetatable({}, {__index = Heap})
    self.a = {}
    self.upper_func = upper_func
    self.upper = function(k1, k2)
        assert(k1 < k2)
        if k1 == 0 then
            return false
        else
            return upper_func(self.a[k1], self.a[k2])
        end
    end
    self.lower = function(k1, k2)
        return not self.upper(k1, k2)
    end
    return self
end

function Heap:count()
    return #self.a
end

function Heap:_swap(k1, k2)
    local old_k1 = self.a[k1]
    self.a[k1] = self.a[k2]
    self.a[k2] = old_k1
end

function Heap:upheap(newk)
    local ku = newk // 2
    local k = newk
    while ku > 0 and self.lower(ku, k) do
        self:_swap(ku, k)
        k = k//2
        ku = ku//2
    end
end

function Heap:insertq(e)
    table.insert(self.a, e)
    self:upheap(#self.a)
end

function Heap:downheap(newk)
    local k = newk
    while k <= #self.a//2 do
        local kdl = k*2
        local kdr = kdl + 1
        local kd
        if kdr <= #self.a and self.lower(kdl, kdr) then
            kd = kdr
        else
            kd = kdl
        end
        if self.upper(k, kd) then
            break
        end
        self:_swap(k, kd)
        k = kd
    end
end

function Heap:top()
    assert(#self.a >= 1)
    return self.a[1]
end

function Heap:remove_top()
    assert(#self.a >= 1)
    local v = self.a[1]
    self:_swap(1, #self.a)
    table.remove(self.a)
    self:downheap(1)
    return v
end

function Heap:replace_top(e)
    assert(#self.a >= 1)
    local old_v = self.a[1]
    local swapped = false
    if self.upper_func(old_v, e) then
        self.a[1] = e
        self:downheap(1)
        swapped = true
    end
    return swapped, old_v
end

-- dijkstra's algorithm
local function find_shortest_path_all(adj_list, src)
    local from1 = {}
    local prevs = {}
    local q = Heap.new(function (v1, v2)
        return v1[2] < v2[2]
    end)
    local proved = {}
    q:insertq({src, 0, {}})
    while q:count() > 0 do
        local elem = q:remove_top()
        local cur_v, cur_cost, path = table.unpack(elem)
        if not proved[cur_v] then
            proved[cur_v] = true
            --[[
            if cur_v == dst then
                return cur_cost
            end
            ]]
            path = {table.unpack(path), cur_v}
            for _, link in ipairs(adj_list[cur_v]) do
                local to, cost = table.unpack(link)
                if not proved[to] then
                    -- compare costs
                    local before = from1[to]
                    local candidate = cur_cost + cost
                    if not before or candidate < before then
                        from1[to] = candidate
                        prevs[to] = cur_v
                        q:insertq({to, candidate, path})
                    end
                end
            end
        end
    end
    return from1, prevs
end

local function make_path(prevs, src, dst)
    local path = {}
    path[#path+1] = dst
    local cur = dst
    while cur ~= src do
        local next = prevs[cur]
        path[#path+1] = next
        cur = next
    end
    -- reverse
    for i=1, #path//2 do
        path[i], path[#path-i+1] = path[#path-i+1], path[i]
    end
    return path
end

-- main
local N, M = io.read("n", "n")

local edges = {}
for i=1,M do
    local a, b, cost = io.read("n", "n", "n")
    edges[#edges+1] = {a, b, cost}
end

local adj_list = {}
for i=1,N do
    adj_list[i] = {}
end

local edge_check = {}
for s=1,N do
    edge_check[s] = {}
end

for i=1,M do
    local a, b, cost = table.unpack(edges[i])
    local list = adj_list[a]
    list[#list+1] = {b, cost}
    local list2 = adj_list[b]
    list2[#list2+1] = {a, cost}
    local small = math.min(a, b)
    local big = math.max(a, b)
    edge_check[small][big] = 0
end


for s=1,N do
    local c, prevs = find_shortest_path_all(adj_list, s)
    for dd=1,N do
        if dd ~= s then
            local ss = prevs[dd]
            local small = math.min(ss, dd)
            local big = math.max(ss, dd)
            edge_check[small][big] = edge_check[small][big] + 1
        end
    end
end

local ans = 0
for s=1,N do
    for d=s+1,N do
        local count = edge_check[s][d]
        if count then
            --print(s,d,count)
            if count == 0 then
                ans = ans + 1
            end
        end
    end
end
print(ans)