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

type Bound = (Vertex, Vertex)
type Vertex = Int
type Weight = Int
type Edge = ((Vertex, Vertex), Weight)
type Path = [Vertex]
type Graph = A.Array Vertex (S.Set (Vertex, Weight))

buildG :: Bound -> [Edge] -> Graph
buildG b = A.accumArray (flip S.insert) S.empty b . map (\((s, t), w) -> (s, (t, w)))

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

size :: Graph -> Int
size g = let (i,j) = A.bounds g in j - i + 1

readDirectedEdge :: B.ByteString -> [Edge]
readDirectedEdge = map (constructOneWay . map readInt . B.words) . B.lines

constructOneWay :: [Int] -> Edge
constructOneWay [s,t,w] = ((s, t), w)
constructOneWay _ = undefined

readInt :: B.ByteString -> Int
readInt = maybe undefined fst . B.readInt

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

score :: Int -> Graph -> Maybe Weight
score n g = guard (im1 M.! n == im2 M.! n) >> return (im1 M.! n)
  where
    im1 = bellmanFord g 1
    im2 = _bellmanFord g (size g) im1

type Memo = M.IntMap Weight

bellmanFord :: Graph -> Vertex -> Memo
bellmanFord g s = _bellmanFord g n m0
 where
  n = size g
  m0 = M.singleton s 0

_bellmanFord :: Graph -> Int -> Memo -> Memo
_bellmanFord g n m
  | n == 0 = m
  | otherwise = _bellmanFord g (pred n) (M.foldrWithKey (move g) m m)

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