Problem:
All Pairs Shortest Path

Input

An edge-weighted graph G (V, E).

|V| |E|
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|E|-1

|V| is the number of vertices and |E| is the number of edges in G. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively.

si and ti represent source and target vertices of i-th edge (directed) and di represents the cost of the i-th edge.

Output

If the graph contains a negative cycle (a cycle whose sum of edge costs is a negative value), print

NEGATIVE CYCLE

in a line.

Otherwise, print

D0,0 D0,1 ... D0,|V|-1
D1,0 D1,1 ... D1,|V|-1
:
D|V|-1,0 D1,1 ... D|V|-1,|V|-1

The output consists of |V| lines. For each ith line, print the cost of the shortest path from vertex i to each vertex j (j = 0, 1, ... |V|-1) respectively. If there is no path from vertex i to vertex j, print "INF". Print a space between the costs.

Constraints

1 ≤ |V| ≤ 100

0 ≤ |E| ≤ 9900

-2 × 107 ≤ di ≤ 2 × 107

There are no parallel edges

There are no self-loops

Sample Input 1

4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 7

Sample Output 1

0 1 3 4
INF 0 2 3
INF INF 0 1
INF INF 7 0

Sample Input 2

4 6
0 1 1
0 2 -5
1 2 2
1 3 4
2 3 1
3 2 7

Sample Output 2

0 1 -5 -4
INF 0 2 3
INF INF 0 1
INF INF 7 0

Sample Input 3

4 6
0 1 1
0 2 5
1 2 2
1 3 4
2 3 1
3 2 -7

Sample Output 3

NEGATIVE CYCLE

Solution in Ruby (judge verdict: Runtime Error)

lines = $stdin.read
array = lines.split("\n")

#
# :u ノードのインデックス
# :k u の出次数
# :v u に隣接する頂点の番号
# :w 隣接する頂点への重み
# ---
# :visited 深さ優先探索用
# ---
# 閉路の判定のため深さ優先探索も実装してみる
#   深さ優先探索で親ノードへの戻り辺があれば、それは閉路である。トポロジカルソートでも検出できる。
#   Wikipedia - 閉路 より
#
INF  = 999999999
Node = Struct.new(:u, :k, :v, :w, :visited)

class Graph
  attr :nodes, :dist
  def initialize(n)
    @nodes = Array.new(n){ Node.new }
    @nodes = @nodes.map.with_index do |node,idx|
      node.u = idx
      node
    end
    @dist = Array.new(n).map{Array.new(n, 0)}
  end

  def add_graph_edge(u, v, w)
    #puts "#{u} -> #{v} (#{w})"
    if @nodes[u].v.nil?
      @nodes[u].v = [v]
      @nodes[u].w = {v=>w}
    elsif @nodes[u].v.is_a?(Array)
      @nodes[u].v << v
      @nodes[u].w = {v=>w}.merge(@nodes[u].w)
    else
      @nodes[u].v = [@nodes[u].v, v]
      @nodes[u].w = {v=>w}.merge(@nodes[u].w)
    end
    @nodes[u].k = if @nodes[u].v.is_a?(Array)
                    @nodes[u].v.length
                  else
                    1
                  end
  end

  def warshall_floyd()
    # initialize
    for i in 0...@nodes.length
      for j in 0...@nodes.length
        @dist[i][j] = if not @nodes[i].w.nil? and @nodes[i].w.has_key?(j)
                        @nodes[i].w[j]
                      else
                        INF
                      end
        @dist[i][j] = 0 if i==j
      end
    end

    # calc
    for k in 0...@nodes.length
      for i in 0...@nodes.length
        for j in 0...@nodes.length
          if @dist[i][j] > @dist[i][k] + @dist[k][j]
            @dist[i][j] = @dist[i][k] + @dist[k][j]
          end
        end
      end
    end
  end

  def collect_weight(node_idxs)
    # p node_idxs
    ans = 0
    node_idxs.each_cons(2) do |ns|
      #p ns
      #p @nodes[ns.first].w
      #p ns.last
      ans += @nodes[ns.first].w[ns.last].to_i
    end
    p ans
    ans
  end

  def has_negative_cycle?()
    @nodes.any? do |node|
      @nodes = @nodes.map{|n| n.visited = false; n}

      rec,weight = dfs(node.u, node.u)
      rec = rec.uniq
      #p rec
      #p weight
      ans = rec.any? do |arr|
        #p weight
        #p @nodes[arr.last].w.to_a.first.last
        @nodes[arr.last].v.include?(node.u) \
          and @nodes[arr.last].w.to_a.first.last < 0
      end
      #puts "ans = #{ans}"
      ans
    end
  end

  def dfs(start = 0, init = 0, history = [], rec = [], weight = 0)
    #puts "  start visit = #{@nodes[start].to_s}"
    @nodes[start].visited = true
    history << start

    return rec,weight if @nodes[start].v.nil?

    for i in @nodes[start].v
      if @nodes[i].visited
        # 探索終わり
        rec << history
      else
        # そうでない場合さらに探索
        weight += @nodes[start].w[i]
        dfs(i, init, history, rec, weight)
      end
    end
    #puts "  end visited = #{@nodes[start].to_s}"
    return rec,weight
  end
end

V,E = array[0].split(" ").map(&:to_i)
graph = Graph.new(V)

array[1..E].each do |s|
  s,t,d = s.split(" ").map(&:to_i)
  graph.add_graph_edge(s,t,d)
end

# execute WarshallFloyd !
graph.warshall_floyd()

if graph.has_negative_cycle?
  puts "NEGATIVE CYCLE"
else
  graph.dist.each do |d|
    puts d.map{|d| if d == INF; "INF" else d end}.join(" ")
  end
end