#include <bits/stdc++.h>
using namespace std;
const int mac = 1e5 + 10;
const long long inf = 1e18 + 10;
struct node {
  int id;
  long long s;
  bool operator<(const node &a) const { return s > a.s; }
};
struct Edge {
  int to, next, w;
} eg[mac * 20];
long long dis[mac * 10];
int head[mac * 10], tree1[mac << 2], tree2[mac << 2];
int idx, pa[mac], pb[mac], num;
bool vis[mac * 10];
void add(int u, int v, int w) {
  eg[num] = Edge{v, head[u], w};
  head[u] = num++;
}
void build1(int l, int r, int rt) {
  tree1[rt] = ++idx;
  if (l == r) {
    pa[l] = tree1[rt];
    return;
  }
  int mid = (l + r) >> 1;
  build1(l, mid, rt << 1);
  build1(mid + 1, r, rt << 1 | 1);
  add(tree1[rt], tree1[rt << 1], 0);
  add(tree1[rt], tree1[rt << 1 | 1], 0);
}
void build2(int l, int r, int rt) {
  tree2[rt] = ++idx;
  if (l == r) {
    pb[l] = tree2[rt];
    add(pa[l], tree2[rt], 0);
    return;
  }
  int mid = (l + r) >> 1;
  build2(l, mid, rt << 1);
  build2(mid + 1, r, rt << 1 | 1);
  add(tree2[rt << 1], tree2[rt], 0);
  add(tree2[rt << 1 | 1], tree2[rt], 0);
}
void update_to_range(int l, int r, int rt, int st, int L, int R, int w) {
  if (l >= L && r <= R) {
    add(pb[st], tree1[rt], w);
    return;
  }
  int mid = (l + r) >> 1;
  if (mid >= L) update_to_range(l, mid, rt << 1, st, L, R, w);
  if (mid < R) update_to_range(mid + 1, r, rt << 1 | 1, st, L, R, w);
}
void update_to_pos(int l, int r, int rt, int L, int R, int ed, int w) {
  if (l >= L && r <= R) {
    add(tree2[rt], pa[ed], w);
    return;
  }
  int mid = (l + r) >> 1;
  if (mid >= L) update_to_pos(l, mid, rt << 1, L, R, ed, w);
  if (mid < R) update_to_pos(mid + 1, r, rt << 1 | 1, L, R, ed, w);
}
void dij(int st) {
  priority_queue<node> q;
  q.push(node{st, 0});
  dis[st] = 0;
  while (!q.empty()) {
    node now = q.top();
    q.pop();
    int u = now.id;
    if (vis[u]) continue;
    vis[u] = true;
    for (int i = head[u]; i != -1; i = eg[i].next) {
      int v = eg[i].to;
      if (vis[v]) continue;
      if (dis[v] > dis[u] + 1LL * eg[i].w) {
        dis[v] = dis[u] + 1LL * eg[i].w;
        q.push(node{v, dis[v]});
      }
    }
  }
}
int main(int argc, char const *argv[]) {
  int n, q, s;
  scanf("%d%d%d", &n, &q, &s);
  memset(head, -1, sizeof head);
  build1(1, n, 1);
  build2(1, n, 1);
  for (int i = 1; i <= q; i++) {
    int id, u, v, w, l, r;
    scanf("%d", &id);
    if (id == 1) {
      scanf("%d%d%d", &u, &v, &w);
      add(pb[u], pa[v], w);
    } else {
      scanf("%d%d%d%d", &v, &l, &r, &w);
      if (id == 2)
        update_to_range(1, n, 1, v, l, r, w);
      else
        update_to_pos(1, n, 1, l, r, v, w);
    }
  }
  for (int i = 1; i < n * 10; i++) dis[i] = inf;
  dij(pb[s]);
  for (int i = 1; i <= n; i++) {
    if (dis[pb[i]] == inf)
      printf("%d%c", -1, i == n ? '\n' : ' ');
    else
      printf("%lld%c", dis[pb[i]], i == n ? '\n' : ' ');
  }
  return 0;
}
