#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, int> pli; // {距离, 节点}
const ll INF = 1e18;
// 邻接表: graph[u] = {{v, w}, ...} 表示u到v有权重为w的边
vector<vector<pair<int, ll>>> graph;
vector<ll> dist;
vector<int> parent; // 用于记录最短路径
// Dijkstra算法
// n: 节点数(0-indexed), start: 起点
// 返回从start到各点的最短距离数组
void dijkstra(int n, int start) {
dist.assign(n, INF);
parent.assign(n, -1);
dist[start] = 0;
priority_queue<pli, vector<pli>, greater<pli>> pq;
pq.push({0, start});
while (!pq.empty()) {
auto [d, u] = pq.top();
pq.pop();
// 如果当前距离大于已记录距离,跳过
if (d > dist[u]) continue;
for (auto [v, w] : graph[u]) {
if (dist[u] + w < dist[v]) {
dist[v] = dist[u] + w;
parent[v] = u;
pq.push({dist[v], v});
}
}
}
}
// 获取从start到target的最短路径(节点列表)
vector<int> getPath(int target) {
vector<int> path;
if (dist[target] == INF) return path; // 不可达
for (int u = target; u != -1; u = parent[u]) {
path.push_back(u);
}
reverse(path.begin(), path.end());
return path;
}
// ========== 使用示例 ==========
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s; // n个点, m条边, 起点s
cin >> n >> m >> s;
s--; // 转为0-indexed
graph.resize(n);
for (int i = 0; i < m; i++) {
int u, v;
ll w;
cin >> u >> v >> w;
u--; v--; // 转为0-indexed
graph[u].push_back({v, w});
// 如果是无向图,加上: graph[v].push_back({u, w});
}
dijkstra(n, s);
// 输出到各点的最短距离
for (int i = 0; i < n; i++) {
cout << (dist[i] == INF ? -1 : dist[i]) << " ";
}
cout << endl;
// 示例: 输出到某点的路径
// vector<int> path = getPath(target);
return 0;
}