#include <bits/stdc++.h>
#pragma GCC optimize(3)
using namespace std;
inline int read() {
  int num = 0, flag = 1;
  char c = ' ';
  for (; c > '9' || c < '0'; c = getchar())
    if (c == '-') flag = -1;
  for (; c >= '0' && c <= '9';
       num = (num << 1) + (num << 3) + c - 48, c = getchar())
    ;
  return num * flag;
}
int n;
struct Edge {
  int v, w, nxt;
} e[2000005 << 1];
int lst[1000005], Edgetot = 0;
inline void addedge(int u, int v, int w) {
  e[++Edgetot] = (Edge){v, w, lst[u]};
  lst[u] = Edgetot;
}
struct Segment_tree {
  int l, r;
} b[1000005 << 2];
int num = 0;
void build1(int k, int l, int r) {
  b[k].l = l, b[k].r = r, num = max(num, k);
  if (l == r) {
    addedge(k + n, l, 0);
    return;
  }
  int mid = (l + r) >> 1;
  build1((k << 1), l, mid);
  build1((k << 1 | 1), mid + 1, r);
  addedge(k + n, (k << 1) + n, 0);
  addedge(k + n, (k << 1 | 1) + n, 0);
}
void build2(int k, int l, int r) {
  if (l == r) {
    addedge(l, k + n + num, 0);
    return;
  }
  int mid = (l + r) >> 1;
  build2((k << 1), l, mid);
  build2((k << 1 | 1), mid + 1, r);
  addedge((k << 1) + n + num, k + n + num, 0);
  addedge((k << 1 | 1) + n + num, k + n + num, 0);
}
void update1(int k, int ul, int ur, int u, int val) {
  int l = b[k].l, r = b[k].r, mid = (l + r) >> 1;
  if (ul <= l && r <= ur) {
    addedge(u, k + n, val);
    return;
  }
  if (mid >= ur)
    update1((k << 1), ul, ur, u, val);
  else if (mid < ul)
    update1((k << 1 | 1), ul, ur, u, val);
  else {
    update1((k << 1), ul, mid, u, val);
    update1((k << 1 | 1), mid + 1, ur, u, val);
  }
}
void update2(int k, int ul, int ur, int u, int val) {
  int l = b[k].l, r = b[k].r, mid = (l + r) >> 1;
  if (ul <= l && r <= ur) {
    addedge(k + n + num, u, val);
    return;
  }
  if (mid >= ur)
    update2((k << 1), ul, ur, u, val);
  else if (mid < ul)
    update2((k << 1 | 1), ul, ur, u, val);
  else {
    update2((k << 1), ul, mid, u, val);
    update2((k << 1 | 1), mid + 1, ur, u, val);
  }
}
struct node {
  int id;
  long long val;
  bool operator<(const node b) const { return val > b.val; }
};
priority_queue<node> Q;
long long dis[1000005 * 5];
char used[1000005 * 5];
void Dij(int s) {
  memset(used, 0, sizeof(used));
  for (int i = (1); i <= (1000000); i++) dis[i] = (1ll << 60);
  dis[s] = 0;
  Q.push((node){s, 0});
  while (!Q.empty()) {
    int u = Q.top().id;
    Q.pop();
    if (used[u]) continue;
    used[u] = 1;
    for (int i = lst[u]; i; i = e[i].nxt) {
      int v = e[i].v;
      if (dis[v] > dis[u] + e[i].w) {
        dis[v] = dis[u] + e[i].w;
        Q.push((node){v, dis[v]});
      }
    }
  }
}
signed main() {
  n = read();
  build1(1, 1, n);
  build2(1, 1, n);
  int Tnum = read(), S = read();
  while (Tnum--) {
    int opt = read(), u = read();
    if (opt == 1) {
      int v = read(), w = read();
      addedge(u, v, w);
    } else if (opt == 2) {
      int l = read(), r = read(), w = read();
      update1(1, l, r, u, w);
    } else {
      int l = read(), r = read(), w = read();
      update2(1, l, r, u, w);
    }
  }
  Dij(S);
  for (int i = (1); i <= (n); i++) {
    if (dis[i] == (1ll << 60)) {
      printf("-1 ");
    } else {
      printf("%lld ", dis[i]);
    }
  }
  return 0;
}
