import Control.Monad
import Data.IntMap.Strict ((!)) 
import qualified Data.IntMap.Strict as M 
import qualified Data.Set as S 
import qualified Data.ByteString.Char8 as B 
import qualified Data.Array.IArray as A 
import Data.Maybe 

type Vertex = Int 
type Weight = Int 
type Edge = (Vertex, (Vertex, Weight)) 
type Graph = A.Array Vertex (S.Set (Vertex, Weight))
type Memo = M.IntMap Weight

buildG :: Int -> [Edge] -> Graph 
buildG n = A.accumArray (flip S.insert) S.empty (1, n) 

from :: Graph -> Vertex -> S.Set (Vertex, Weight) 
from g = (g A.!) 

readDirectedEdge :: B.ByteString -> [Edge] 
readDirectedEdge = map ((\[s,t,w] -> (s,(t,w))) . map readVertex . B.words) . B.lines 

readVertex :: B.ByteString -> Vertex 
readVertex = fst . fromJust . B.readInt

main :: IO ()
main = do
  [n,_] <- map read . words <$> getLine
  es <- readDirectedEdge <$> B.getContents
  let g = buildG n es
  putStrLn $ maybe "inf" show (score n g)

score :: Int -> Graph -> Maybe Weight
score n g = guard (im1!n == im2!n) >> return (im1!n)
  where
    im0 = M.singleton 1 0
    im1 = bellman_ford g n im0
    im2 = bellman_ford g (n + 1) im1

bellman_ford :: Graph -> Int -> Memo -> Memo
bellman_ford g n im
  | n == 1 = im
  | otherwise = bellman_ford g (n - 1) (M.foldrWithKey (move g) im im)

move :: Graph -> Vertex -> Weight -> Memo -> Memo
move g s aw im = S.foldr update im (from g s)
  where 
    update (t,w) acc
      | M.notMember t acc || (acc!t) < aw + w = M.insert t (aw + w) acc
      | otherwise = acc