#include <cstdio>
#include <algorithm>
#include <queue>
#define long long long
#define INF 0x7fffffff
const int MAX_NODE=100001,MAX_EDGE=200001;
using namespace std;
typedef pair<long,int> pii;
long dist[MAX_NODE];
int first[MAX_NODE],n;
bool vis[MAX_NODE];
struct forward_star {
int to;
int weight;
int next;
forward_star() {weight=INF;next=to=-1;}
};
void Dijistra(int st,forward_star *G) {
priority_queue<pii,vector<pii>,greater<pii> > q;
dist[st]=0;
q.push(make_pair(dist[st],st)); //两个元素依次是距离、编号,注意距离为long long
while(!q.empty()) { //如果队列不空
int cur=q.top().second;
if(vis[cur]) {
q.pop();
continue;
}
for(int i=first[cur]; i!=-1; i=G[i].next) {
if(!vis[G[i].to]&&dist[cur]+G[i].weight<dist[G[i].to]) { //如果到点G[i].to不是最短路径
dist[G[i].to]=dist[cur]+G[i].weight; //更新到i的最小距离
q.push(make_pair(dist[G[i].to],G[i].to));
}
}
vis[cur]=1;
q.pop();
}
}
int main() {
static forward_star G[MAX_EDGE];
int m,st;
scanf("%d%d%d",&n,&m,&st);
fill(dist+1,dist+n+1,INF); //原点到每个点的距离
//注意点是从1开始的
fill(first,first+n+1,-1); //边的编号
for(int i=0; i<m; i++) {
int from,to,w;
scanf("%d%d%d",&from,&to,&w);
G[i].next=first[from];
G[i].to=to;
G[i].weight=w;
first[from]=i;
} //初始化
Dijistra(st,G);
printf("%lld",dist[1]);
for(int i=2;i<=n;i++)
printf(" %lld",dist[i]);
return 0;
}