#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1000;
const int INF = 1000000000;
int Map[maxn][maxn];
int n, m, s;
int d[maxn];
bool visited[maxn] = {false};
void dijkstra(int s) {
fill(d, d + n, INF);
d[s] = 0;
for (int i = 0; i < n; i++) {
int u = -1, MIN = INF; //u 使得d[u]最小
for (int j = 0; j < n; j++) {
if (!visited[j] && d[j] < MIN) {
u = j;
MIN = d[j];
}
}
//找不到小于INF的d[u],说明剩下的点和s不连通
if (u == -1) return;
visited[u] = true;
//s到v最短还是u到v最短,更新最短路径
for (int v = 0; v < n; v++) {
if (!visited[v] && Map[u][v] < INF && d[v] > d[u] + Map[u][v]) {
d[v] = d[u] + Map[u][v];
}
}
}
}
int main() {
int u, v, w;
scanf("%d%d%d", &n, &m, &s);
fill(Map[0], Map[0] + maxn * maxn, INF);
for (int i = 0; i < m; i++) {
scanf("%d %d %d", &u, &v, &w);
Map[u][v] = Map[v][u] = w;
}
dijkstra(s);
for (int i = 0; i < n; i++) {
printf("%d ", d[i]);
}
return 0;
}
/******************
6 8 0
0 1 1
0 3 4
0 4 4
1 3 2
2 5 1
3 2 2
3 4 3
4 5 3
输出:0 1 5 3 4 6
*******************/