#include<bits/stdc++.h>
using namespace std;
const int inf=INT_MAX;
void djs(int v,vector<vector<pair<int,int>>>&edge,int sources){
vector<int>dis(v,inf);
//初始距离为最大
dis[sources]=0;
//创建最小堆
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>pq;
pq.push({0,sources});//距离,点
while(!pq.empty()){
int w=pq.top().second;//点
int d=pq.top().first;距离
pq.pop();
if(d>dis[w]) continue;
for(auto&d:edge[w]){//
int a=d.first;//邻接点
int b=d.second;//权
if(b+dis[w]<dis[a]){//如果一步不能到达,则直接更新(默认一步为inf)
dis[a]=b+dis[w];//成功后则加入pq多次比较
pq.push({dis[a],a});
}
}
}
//循环完后dis存储的是目的短点到各个点的最距离
for(int i=0;i<v;i++){
cout<<dis[i]<<" ";
}
}
int main(){
int n,m,s;
cin>>n>>m>>s;
vector<vector<pair<int,int>>>edge(n);
int tmp=m;
while(tmp--){
int a,b,c;//a->b (c)
cin>>a>>b>>c;
a--,b--;
edge[a].push_back({b,c});
}
//如果是从1开始的 要符合dis里面的索引,带入值要-1,点1在edge要--变成0才符合索引
djs(n,edge,s-1);
}