module type SEMIRING = 
sig
	type t
	val add : t -> t -> t
	val mul : t -> t -> t
	val unit : t
	val zero : t
	
	val debug : t -> string
end

module type VECT = 
	functor (T : SEMIRING) ->
		sig
			type t
			val zero : int -> t
			val list2vect : (T.t list) -> t 
			val vect2list : t -> (T.t list)
			val add : t -> t -> t
			val dot : t -> t -> T.t
			
			val debug : t -> string
		end

module Vect : VECT = 
	functor (T : SEMIRING) -> struct
		type t = (T.t list) 
		let list2vect xs = xs
		let vect2list xs = xs
		let rec zero n = if n = 0 then [] else T.zero :: zero (n-1)
		
		let fzip f a b = List.map (fun (x,y) -> f x y) (List.combine a b)
		let add a b = fzip T.add a b
		let dot a b = List.fold_left T.add T.zero (fzip T.mul a b)
		
		let debug v = Printf.sprintf "[%s]" (String.concat "; " (List.map T.debug v))
			
	end

module type MAT = 
	functor (T : SEMIRING) ->
		sig 
			type t
			val unit : int -> t
			val zero : int -> t
			val trans : t -> t (* ??¢??? *)
			val add : t -> t -> t
			val mul : t -> t -> t
			val list2mat : (T.t list) list -> t
			val mat2list : t -> (T.t list) list
			val vect2mat : Vect(T).t -> t
			
			val debug : t -> string
		end

module IntSemiring = 
struct
	type t = int
	let add a b = a + b
	let mul a b = a * b
	let unit = 1
	let zero = 0
	
	let debug v = Printf.sprintf "%d" v
end

module BoolSemiring = 
struct
	type t = bool
	let add a b = a <> b
	let mul a b = a && b
	let unit = true
	let zero = false
	
	let debug v = if v then "true" else "false" 
end

type tropical = Int of int | Inf

module TropicalSemiring = 
struct
	type t = tropical
	let add a b = 
		match a with 
		| Inf -> b
		| Int ia -> 
			match b with
			| Inf -> a
			| Int ib -> Int (min ia ib)
	let mul a b = 
		match a with 
		| Inf -> Inf
		| Int ia -> 
			match b with
			| Inf -> Inf
			| Int ib -> Int (ia + ib)
	
	let unit = Int 0
	let zero = Inf
	
	let debug v = 
		match v with 
		| Inf -> "INF"
		| Int a -> Printf.sprintf "%d" a
end

module Mat : MAT = 
	functor (T : SEMIRING) -> struct
		module Vt = Vect(T)
		type t = Vt.t list
		let fzip f a b = List.map (fun (x,y) -> f x y) (List.combine a b)
		let trans v = 
			let vt = List.map Vt.vect2list v in
			let rec trans_sub a = 
				match a with
				| [] -> []
				| x :: xs -> 
					if x = [] then [] else
					(Vt.list2vect (List.map List.hd a)) :: trans_sub (List.map List.tl a) in
			trans_sub vt
		let add a b = fzip Vt.add a b
		let mul a b = 
			let tb = trans b in
			let rec mul_sub va vb = 
				match va with
				| [] -> []
				| x :: xs -> (Vt.list2vect (List.map (fun t -> Vt.dot x t) vb)) :: (mul_sub xs vb) in
			mul_sub a tb
		let zero n = 
			let rec zero_sub nn = if nn = 0 then [] else Vt.zero n :: (zero_sub (nn-1)) 
				in zero_sub n
		let unit n = 
			let rec onehot nn x = 
				if nn = 0 then [] else
					(if x = nn then T.unit else T.zero) :: (onehot (nn-1) x) in
			let rec unit_sub a = 
				if a = 0 then [] else
					(Vt.list2vect (onehot n a)) :: (unit_sub (a-1)) in
			unit_sub n
		
		let list2mat v = List.map Vt.list2vect v
		let mat2list v = List.map Vt.vect2list v
		let vect2mat v = [v]
		
		let debug v = Printf.sprintf "[\n%s]" (String.concat ";\n" (List.map Vt.debug v))
		
	end



module TropicalMat = Mat(TropicalSemiring)


let _ = 
	let (n,m) = Scanf.scanf "%d %d\n" (fun a b -> (a,b)) in
	let v = (Array.make_matrix n n Inf) in
	let _ = 
		for i = 0 to (n-1) do
			Array.set v.(i) i (Int 0)
		done;
		for i = 0 to (m-1) do
			let (s,t,d) = Scanf.scanf "%d %d %d\n" (fun a b c -> (a,b,c)) in
			Array.set v.(s) t (Int d)
		done in
	let mat = TropicalMat.list2mat (Array.to_list (Array.map Array.to_list v)) in
(*
	let _ = (print_string (TropicalMat.debug mat)) in
*)
	let rec matpow x y b = 
		if y = 1 then b else
			let tx = matpow x (y/2) b in
			let ttx = TropicalMat.mul tx tx in
			if y mod 2 = 1 then TropicalMat.mul ttx b else ttx in
	let ansma = (matpow mat n mat) in
(*
	let _ = (print_string (TropicalMat.debug ansma)) in
*)
	let ans = Array.of_list (List.map Array.of_list (TropicalMat.mat2list ansma)) in
	let ok = ref true in
	let _ = 
		for i = 0 to (n-1) do
			match ans.(i).(i) with
			| Inf -> ok := false
			| Int x -> ok := (!ok) && (x >= 0)
		done in
	if not !ok then Printf.printf "NEGATIVE CYCLE\n" else
		for i = 0 to (n-1) do
			for j = 0 to (n-1) do
				Printf.printf "%s%c" (TropicalSemiring.debug ans.(i).(j)) (if j = (n-1) then '\n' else ' ')
			done
		done
	
	
	

Measured memory_bytes: 9056