import Data.IntMap ((!))
import qualified Data.IntMap as M
import qualified Data.Set as S
import qualified Data.ByteString.Char8 as B
import Control.Applicative
import Data.Maybe
import Data.List
 
type Weight = Int
type Vertex = Int
 
type PriorityQueue = S.Set (Weight, Vertex)
nullq = S.null
empty = S.empty 
push c v = S.insert (c,v)
pop = S.deleteFindMin
 
readEdge = (\[s,t,d] -> (s,[(t,d)])) . map (fst . fromJust . B.readInt) . B.words
 
main = do
 [nv,ne,v0] <- map read . words <$> getLine
 es <- sort . map readEdge . B.lines <$> B.getContents
 let g = foldr (\(k,v) acc -> M.insertWith (flip (++)) k v acc) M.empty es
 mapM_ (putStrLn . maybe "INF" show . sumOfWeight g nv ne v0 es) [0..nv-1]
 
sumOfWeight g nv ne v0 es v = M.lookup v imr
 where
  (imr,_) = until (nullq . snd) (dijkstra g) (im0,q0)
  im0 = M.singleton v0 0
  q0 = push 0 v0 S.empty

dijkstra g (im,q) = (im',q'')
 where
  ((d,v),q') = pop q
  im' = foldl' (\acc (b,c) -> M.insertWith min b (d+c) acc) im vns
  q'' = foldl' (\acc (b,c) -> push (d+c) b acc) q' vns
  vns = filter (\(b,c) -> M.notMember b im || d+c < M.findWithDefault 0 b im) (M.findWithDefault [] v g)