#include<bits/stdc++.h>
using namespace std;

int bottom;
int outside_color;

// Library.
#include<cassert>
#include<map>
#include<vector>
#include<cmath>
#include<queue>
#include<algorithm>
// Type.
typedef int Label;
typedef long long Weight;
// Class.
template<typename Vertex, typename Edge>
class PlaneGraph {
public:
  void insert(const Vertex& v);
  void insert(Edge e);
  const PlaneGraph<Vertex, Edge> dualgraph() const;
  const std::map<Label, Weight> Dijkstra(const Label& start) const;
private:
  void dualgraph_color(std::map<Label, std::map<Label, int>>& color, int c, const Edge& e, const std::map<Label, std::vector<Edge>>& edge) const;
  std::map<Label, Vertex> V;
  std::map<Label, std::vector<Edge>> E;
};
// Implement.
template<typename Vertex, typename Edge>
void PlaneGraph<Vertex, Edge>::insert(const Vertex& v) {
  V[v.label] = v;
}
template<typename Vertex, typename Edge>
void PlaneGraph<Vertex, Edge>::insert(Edge e) {
  assert(V.find(e.from) != std::end(V));
  assert(V.find(e.to) != std::end(V));
  E[e.from].push_back(e);
//   std::swap(e.from, e.to);
//   E[e.from].push_back(e);
}
template<typename Vertex, typename Edge>
const PlaneGraph<Vertex, Edge> PlaneGraph<Vertex, Edge>::dualgraph() const {
  // Sort edges counterclockwise.
  auto edge = E;
  for(auto& list: edge) if(!list.second.empty()) {
    std::sort(std::begin(list.second), std::end(list.second), [&](const Edge& lhs, const Edge& rhs) {
      double l = std::atan2(V.at(lhs.to).y - V.at(lhs.from).y, V.at(lhs.to).x - V.at(lhs.from).x);
      double r = std::atan2(V.at(rhs.to).y - V.at(rhs.from).y, V.at(rhs.to).x - V.at(rhs.from).x);
      return l < r;
    });
    list.second.push_back(list.second.front());
  }
  // Color edges.
  std::map<Label, std::map<Label, int>> color;
  int c = 1;
  for(const auto& list: edge) {
    for(const auto& e: list.second) if(!color[e.from].count(e.to)) dualgraph_color(color, c++, e, edge);
    if(list.first == bottom) outside_color = color[list.second.front().from][list.second.front().to];
  }
  // Construct the dualgraph.
  PlaneGraph<Vertex, Edge> result;
  std::vector<std::vector<bool>> used(c, std::vector<bool>(c, false));
  for(int i = 1; i < c; ++i) result.insert(Vertex({i}));
  for(const auto& list: E) for(const auto& e: list.second) if(!used[color[e.from][e.to]][color[e.to][e.from]]) {
    used[color[e.from][e.to]][color[e.to][e.from]] = true;
    used[color[e.to][e.from]][color[e.from][e.to]] = true;
    result.insert(Edge({color[e.from][e.to], color[e.to][e.from], 1}));
  }
  return result;
}
template<typename Vertex, typename Edge>
void PlaneGraph<Vertex, Edge>::dualgraph_color(std::map<Label, std::map<Label, int>>& color, int c, const Edge& e, const std::map<Label, std::vector<Edge>>& edge) const {
  color[e.from][e.to] = c;
  for(auto it = edge.at(e.to).rbegin(); it != edge.at(e.to).rend(); ++it) if(it->to == e.from) {
    ++it;
    if(!color[it->from].count(it->to)) dualgraph_color(color, c, *it, edge);
    break;
  }
}
template<typename Vertex, typename Edge>
const std::map<Label, Weight> PlaneGraph<Vertex, Edge>::Dijkstra(const Label& start) const {
  std::map<Label, Weight> result;
  std::priority_queue<Edge, std::vector<Edge>, std::function<bool(Edge, Edge)>> q([](Edge lhs, Edge rhs) {
    return lhs.weight > rhs.weight;
  });
  q.push(Edge({start, start, 0}));
  while(!q.empty()) {
    auto cur = q.top();
    q.pop();
    if(result.count(cur.to)) continue;
    result[cur.to] = cur.weight;
    if(E.count(cur.to)) for(const auto& nex: E.at(cur.to)) if(!result.count(nex.to)) q.push(Edge({nex.from, nex.to, cur.weight + nex.weight}));
  }
  return result;
}
////////////////////////////////////////
// Configuration.
struct Vertex {Label label; double x, y;};
struct Edge {Label from, to; Weight weight;};
////////////////////////////////////////
#include<bits/stdc++.h>
using namespace std;
int main() {
  int V, E, r;
  cin >> V >> E >> r;
  PlaneGraph<Vertex, Edge> G;
  for(int i = 0; i < V; ++i) G.insert(Vertex({i}));
  for(int i = 0; i < E; ++i) {
    int s, t;
    Weight d;
    cin >> s >> t >> d;
    G.insert(Edge({s, t, d}));
  }
  auto distance = G.Dijkstra(r);
  for(int i = 0; i < V; ++i) {
    if(distance.count(i)) cout << distance[i] << endl;
    else                  cout << "INF" << endl;
  }
}

Measured memory_bytes: 36736