#include <bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 1;
long long d[maxn << 1], inf;
int n, Q, s;
vector<int> to[maxn << 1], w[maxn << 1];
void addEdge(int x, int y, int z) {
  to[x].push_back(y);
  w[x].push_back(z);
  return;
}
struct node {
  int i;
  long long dis;
};
bool operator<(node a, node b) { return a.dis > b.dis; }
priority_queue<node> q;
void buildtree(int k1, int l, int r) {
  if (l == r) {
    addEdge(k1 + n, l, 0);
    addEdge(l, k1 + maxn + n, 0);
    return;
  }
  int mid = l + r >> 1, lc = k1 << 1, rc = lc | 1;
  buildtree(lc, l, mid);
  buildtree(rc, mid + 1, r);
  addEdge(k1 + n, lc + n, 0);
  addEdge(lc + maxn + n, k1 + maxn + n, 0);
  addEdge(k1 + n, rc + n, 0);
  addEdge(rc + maxn + n, k1 + maxn + n, 0);
  return;
}
int op, x, y, z, v;
void add(int k1, int l, int r) {
  if (x <= l && r <= y) {
    if (op == 2)
      addEdge(v, k1 + n, z);
    else
      addEdge(k1 + n + maxn, v, z);
    return;
  }
  if (l > y || r < x) return;
  int mid = l + r >> 1, lc = k1 << 1, rc = lc | 1;
  add(lc, l, mid);
  add(rc, mid + 1, r);
  return;
}
void dijkstra() {
  for (int i = 1; i <= maxn * 2; i++) d[i] = inf;
  q.push((node){s, 0});
  d[s] = 0;
  while (!q.empty()) {
    node t = q.top();
    x = t.i;
    q.pop();
    if (d[t.i] != t.dis) continue;
    int siz = to[t.i].size();
    for (int i = 0; i < siz; i++) {
      int v = to[x][i];
      if (d[v] > d[x] + w[x][i]) {
        d[v] = d[x] + w[x][i];
        q.push((node){v, d[v]});
      }
    }
  }
}
int main() {
  inf = 1, inf <<= 60;
  scanf("%d%d%d", &n, &Q, &s);
  buildtree(1, 1, n);
  for (int i = 1; i <= Q; i++) {
    scanf("%d", &op);
    if (op == 1) {
      scanf("%d%d%d", &x, &y, &z);
      addEdge(x, y, z);
    } else {
      scanf("%d%d%d%d", &v, &x, &y, &z);
      add(1, 1, n);
    }
  }
  dijkstra();
  for (int i = 1; i <= n; i++) {
    if (d[i] == inf)
      printf("-1 ");
    else
      printf("%I64d ", d[i]);
  }
  return 0;
}
