#include <bits/stdc++.h>
using namespace std;
template <typename T1, typename T2>
bool umax(T1 &a, const T2 &b) {
  return a < b ? a = b, 1 : 0;
}
template <typename T1, typename T2>
bool umin(T1 &a, const T2 &b) {
  return a > b ? a = b, 1 : 0;
}
template <typename T>
T sqr(T a) {
  return a * a;
}
mt19937 rng(20010709);
const int mod = 1000000007;
const long long INF = 1e18;
const int N = 100005;
const int HALF = 262145;
const int SIZE = HALF * 2 + N;
int n, m, s, id[N];
long long dist[SIZE];
vector<pair<int, long long>> e[SIZE];
priority_queue<pair<long long, int>, vector<pair<long long, int>>,
               greater<pair<long long, int>>>
    cur;
void build(int v, int l, int r);
void getSegments(int v, int l, int r, int cl, int cr, vector<int> &res);
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cin >> n >> m >> s;
  for (int i = 1; i <= n; i++) id[i] = HALF * 2 + i;
  build(1, 1, n);
  for (int i = 0; i < m; i++) {
    int type, v, u, l, r, c;
    vector<int> seg;
    cin >> type;
    if (type == 1) {
      cin >> v >> u >> c;
      e[id[v]].push_back({id[u], c});
    } else if (type == 2) {
      cin >> v >> l >> r >> c;
      getSegments(1, 1, n, l, r, seg);
      for (auto cur : seg) e[id[v]].push_back({cur, c});
    } else if (type == 3) {
      cin >> v >> l >> r >> c;
      getSegments(1, 1, n, l, r, seg);
      for (auto cur : seg) e[cur + HALF].push_back({id[v], c});
    }
  }
  fill(dist, dist + SIZE, INF);
  dist[id[s]] = 0;
  cur.push({dist[id[s]], id[s]});
  while (!cur.empty()) {
    int v = cur.top().second;
    long long cost = cur.top().first;
    cur.pop();
    if (dist[v] < cost) continue;
    for (auto it : e[v]) {
      if (umin(dist[it.first], cost + it.second))
        cur.push({dist[it.first], it.first});
    }
  }
  for (int i = 1; i <= n; i++) {
    if (dist[id[i]] == INF) dist[id[i]] = -1;
    cout << dist[id[i]] << " ";
  }
  cout << "\n"
       << "\n";
  return 0;
}
void build(int v, int l, int r) {
  if (l == r) {
    e[v].push_back({id[l], 0});
    e[v + HALF].push_back({id[l], 0});
    e[id[l]].push_back({v, 0});
    e[id[l]].push_back({v + HALF, 0});
    return;
  }
  int mid = (l + r) / 2;
  build(v * 2, l, mid);
  build(v * 2 + 1, mid + 1, r);
  e[v * 2 + HALF].push_back({v + HALF, 0});
  e[v * 2 + 1 + HALF].push_back({v + HALF, 0});
  e[v].push_back({v * 2, 0});
  e[v].push_back({v * 2 + 1, 0});
}
void getSegments(int v, int l, int r, int cl, int cr, vector<int> &res) {
  if ((l == cl) && (r == cr)) {
    res.push_back(v);
    return;
  }
  int mid = (l + r) / 2;
  if (cl <= mid) getSegments(v * 2, l, mid, cl, min(cr, mid), res);
  if (cr > mid) getSegments(v * 2 + 1, mid + 1, r, max(mid + 1, cl), cr, res);
}
