{-# OPTIONS_GHC -O2 -funbox-strict-fields #-}
module Main (main) where
import           Control.Applicative
import           Control.Monad
import qualified Data.ByteString       as BS
import qualified Data.ByteString.Char8 as B8
import           Data.List
import           Data.Maybe
import           Data.Vector           ((!))
import qualified Data.Vector           as V
import qualified Data.Vector.Mutable   as MV
getInts :: IO [Int]
getInts = unfoldr (B8.readInt . B8.dropWhile (==' ')) <$> BS.getLine

data Edge = Edge {to :: !Int,revIx :: !Int,capIx :: !Int}
  deriving (Show,Eq)
type Graph = V.Vector (V.Vector Edge)

getGraph :: IO (Graph,MV.IOVector Int)
getGraph = do
  v:e:_ <- getInts
  cap <- MV.new (e*2)
  g <- MV.replicate v []
  forM_ [0..e-1] $ \i -> do
    u:v:c:_ <- getInts
    MV.write cap i c
    MV.write cap (i + e) 0
    us <- MV.read g u
    vs <- MV.read g v
    MV.write g u $ Edge v (e+i) i: us
    MV.write g v $ Edge u i (e+i): vs
    return ()
  g' <- V.map (V.fromList . reverse) <$> V.freeze g
  return (g', cap)

main :: IO ()
main = do
  (g,cap) <- getGraph
  r <- maxFlow 0 (V.length g - 1) g cap
  print r
  return ()

{-# INLINE untilJustM #-}
untilJustM :: Monad m => (a -> m (Maybe b)) -> V.Vector a -> m (Maybe b)
untilJustM act xs
  | V.null xs = return Nothing
  | otherwise = let v = V.head xs
                in do
      x <- act v
      case x of
        Nothing -> untilJustM act (V.tail xs)
        Just _  -> return x

maxFlow :: Int -> Int -> Graph -> MV.IOVector Int -> IO Int
maxFlow s t g cap = loop 0
  where
    loop f = do
      used <- MV.replicate (V.length g) False
      df <- dfs maxBound s t g cap used
      if df == 0
        then return f
        else loop (f + df)

dfs :: Int -> Int -> Int -> Graph
  -> MV.IOVector Int
  -> MV.IOVector Bool
  -> IO Int
dfs f v t g cap used
  | v == t = return f
  | otherwise = do
      MV.write used v True
      fromMaybe 0 <$> untilJustM act (g ! v)
  where
    act :: Edge -> IO (Maybe Int)
    act e@Edge {to = to,capIx = ci, revIx = ri} = do
      c <- MV.read cap ci
      isUsed <- MV.read used to
      if c > 0 && not isUsed
      then do
        d <- dfs (min f c) to t g cap used
        if d > 0
        then do
          modifyCap cap e d
          return (Just d)
        else return Nothing
      else return Nothing

modifyCap :: MV.IOVector Int -> Edge -> Int -> IO ()
modifyCap cap Edge {capIx = ci, revIx = ri} d
  = do
  cv <- MV.read cap ci
  cr <- MV.read cap ri
  MV.write cap ci $ cv - d
  MV.write cap ri $ cr + d