#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long l = 0, f = 1;
  char a = getchar();
  for (; a < '0' || a > '9'; a = getchar())
    if (a == '-') f = -1;
  for (; a >= '0' && a <= '9'; a = getchar()) l = l * 10 + a - 48;
  return l * f;
}
const int N = 100005;
struct Segment {
  int l, r;
} t[N << 2];
struct Edge {
  int v, next;
  long long w;
} e[N << 6];
int n, m, s, num = 0, cnt, h[N << 4], vis[N << 4], id[N << 4], id1[N << 4];
long long dis[N << 4];
void insert(int u, int v, long long w) {
  e[++num].v = v, e[num].w = w, e[num].next = h[u], h[u] = num;
}
void build1(int node, int l, int r) {
  id[node] = ++cnt;
  t[node].l = l, t[node].r = r;
  for (int i = l; i <= r; ++i) insert(i, id[node], 0);
  if (l == r) return;
  int mid = (l + r) >> 1;
  build1(node << 1, l, mid);
  build1(node << 1 | 1, mid + 1, r);
}
void build2(int node, int l, int r) {
  id1[node] = ++cnt;
  t[node].l = l, t[node].r = r;
  for (int i = l; i <= r; ++i) insert(id1[node], i, 0);
  if (l == r) return;
  int mid = (l + r) >> 1;
  build2(node << 1, l, mid);
  build2(node << 1 | 1, mid + 1, r);
}
void query1(int node, int l, int r, int v, long long w) {
  if (t[node].l >= l && t[node].r <= r) {
    insert(id[node], v, w);
    return;
  }
  int mid = (t[node].l + t[node].r) >> 1;
  if (l <= mid) query1(node << 1, l, r, v, w);
  if (r > mid) query1(node << 1 | 1, l, r, v, w);
}
void query2(int node, int u, int l, int r, long long w) {
  if (t[node].l >= l && t[node].r <= r) {
    insert(u, id1[node], w);
    return;
  }
  int mid = (t[node].l + t[node].r) >> 1;
  if (l <= mid) query2(node << 1, u, l, r, w);
  if (r > mid) query2(node << 1 | 1, u, l, r, w);
}
void dijkstra() {
  memset(dis, -1, sizeof(dis));
  memset(vis, 0, sizeof(vis));
  priority_queue<pair<long long, int>, vector<pair<long long, int> >,
                 greater<pair<long long, int> > >
      q;
  dis[s] = 0;
  q.push(make_pair(0, s));
  while (!q.empty()) {
    int x = q.top().second;
    q.pop();
    if (vis[x]) continue;
    vis[x] = 1;
    for (int i = h[x]; i; i = e[i].next) {
      int v = e[i].v;
      if (dis[v] == -1 || dis[v] > (long long)dis[x] + e[i].w) {
        dis[v] = (long long)dis[x] + e[i].w;
        q.push(make_pair(dis[v], v));
      }
    }
  }
}
int main(int argc, char const *argv[]) {
  n = read(), m = read(), s = read();
  cnt = n;
  build1(1, 1, n);
  build2(1, 1, n);
  for (int i = 1; i <= m; ++i) {
    int t = read();
    if (t == 1) {
      int u = read(), v = read();
      long long w = read();
      insert(u, v, w);
    }
    if (t == 3) {
      int v = read(), l = read(), r = read();
      long long w = read();
      query1(1, l, r, v, w);
    }
    if (t == 2) {
      int u = read(), l = read(), r = read();
      long long w = read();
      query2(1, u, l, r, w);
    }
  }
  dijkstra();
  for (int i = 1; i <= n; ++i) printf("%I64d ", dis[i]);
  return 0;
}
