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 Control.Applicative
import Data.Maybe
import Data.List

type Cost = Int
type Vertex = Int

type Heap = S.Set (Cost, (Vertex,Vertex))
nullq = S.null
empty = S.empty 
push c (v,vp) = S.insert (c,(v,vp))
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 <- map readEdge . B.lines <$> B.getContents
 let g = foldr (\((s,t),d) acc -> M.insertWith (++) s [(t,d)] 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.empty
  q0 = push 0 (v0,v0) S.empty

dijkstra g (im,q) = (im',q'')
 where
  ((d,(v,vp)),q') = pop q
  im' = M.insertWith min v d im
  q'' = foldr (\(b,c) acc -> push (d+c) (b,v) acc) q' vns
  vns = filter (\(b,c) -> b/=vp && d+c < M.findWithDefault (maxBound::Int) b im) (M.findWithDefault [] v g)