{-# LANGUAGE ViewPatterns, BangPatterns #-}
import Control.Monad
import Data.List
import qualified Data.Set as Set
import qualified Data.Vector as V
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM

type Graph = V.Vector (U.Vector Edge)
type Edge = (Int, Int)

inf :: Int
inf = maxBound `div` 2

dijkstra :: Graph -> Int -> U.Vector Int
dijkstra gr start = U.create $ do
  let n = V.length gr
  res <- UM.replicate n inf
  UM.write res start 0
  let go (Set.minView -> Just ((!d, !v), !q)) = do
        cur <- UM.read res v
        if cur < d
          then go q
          else do
            adds <- flip U.filterM (gr V.! v) $ \(!cost, !u) -> do
              old <- UM.read res u
              if old <= d + cost
                then return False
                else do
                  UM.write res u $! d + cost
                  return True
            nexts <- flip (`U.foldM` q) adds $ \(!pq) (_, !u) -> do
              dist <- UM.read res u
              return $! Set.insert (dist, u) pq
            go nexts
      go _ = return ()
  go $ Set.singleton (0, start)
  return res

getInts :: IO [Int]
getInts = map read . words <$> getLine

toEdge :: [Int] -> (Int, Edge)
toEdge [s, t, d] = (s, (d, t))

showDist :: Int -> String
showDist d
  | d == inf = "INF"
  | otherwise = show d

main :: IO ()
main = do
  [v, e, r] <- getInts
  es <- replicateM e $ toEdge <$> getInts
  let graph = V.map U.fromList $ V.accum (flip (:)) (V.replicate v []) es
      dists = dijkstra graph r
  U.mapM_ (putStrLn . showDist) dists