#include <bits/stdc++.h>
using namespace std;
const long long Inf = (long long)(1e20);
int n;
struct edge {
  int to;
  long long cost;
};
vector<edge> G[2000005];
inline void add_edge(int u, int v, long long w) {
  edge temp;
  temp.to = v;
  temp.cost = w;
  G[u].push_back(temp);
}
int vis[2000005];
long long dis[2000005];
int rt1[2000005], rt2[2000005];
inline void spafather(int s) {
  for (int i = 0; i < 2000005; ++i) dis[i] = Inf;
  dis[rt1[s]] = 0ll;
  queue<int> Q;
  Q.push(rt1[s]);
  vis[rt1[s]] = true;
  while (Q.size()) {
    int u = Q.front();
    Q.pop();
    vis[u] = false;
    for (int i = 0; i < (int)(G[u].size()); ++i) {
      int v = G[u][i].to;
      long long len = G[u][i].cost;
      if (dis[v] > dis[u] + len) {
        dis[v] = dis[u] + len;
        if (!vis[v]) {
          vis[v] = true, Q.push(v);
        }
      }
    }
  }
}
int cnt, Size;
struct SegmentTree {
  struct node {
    int l, r;
  } tree[2000005 << 2];
  int build(int l, int r, bool flag) {
    int root = ++cnt;
    if (flag) {
      add_edge(cnt - Size, cnt, 0);
    }
    if (l == r) {
      if (flag) {
        return rt2[l] = cnt;
      } else {
        return rt1[l] = cnt;
      }
    }
    int mid = (l + r) >> 1;
    tree[root].l = build(l, mid, flag);
    tree[root].r = build(mid + 1, r, flag);
    if (flag) {
      add_edge(tree[root].l, root, 0);
      add_edge(tree[root].r, root, 0);
    } else {
      add_edge(root, tree[root].l, 0);
      add_edge(root, tree[root].r, 0);
    }
    return root;
  }
  void update(int L, int R, int l, int r, int root, bool flag) {
    if (L <= l && r <= R) {
      if (flag) {
        add_edge(cnt, root, 0);
      } else {
        add_edge(root, cnt, 0);
      }
      return;
    }
    int mid = (l + r) >> 1;
    if (L <= mid) {
      update(L, R, l, mid, tree[root].l, flag);
    }
    if (mid < R) {
      update(L, R, mid + 1, r, tree[root].r, flag);
    }
  }
} Seg1, Seg2;
inline void init() {
  cnt = 0;
  Seg1.build(1, n, 0);
  Size = cnt;
  Seg2.build(1, n, 1);
}
inline void update(int l1, int r1, int l2, int r2, long long w) {
  int cnt1 = ++cnt;
  Seg2.update(l1, r1, 1, n, Size + 1, 0);
  int cnt2 = ++cnt;
  Seg1.update(l2, r2, 1, n, 1, 1);
  add_edge(cnt1, cnt2, w);
}
int main() {
  int q, s;
  scanf("%d%d%d", &n, &q, &s);
  init();
  while (q--) {
    int op;
    scanf("%d", &op);
    long long w;
    if (op == 1) {
      int u, v;
      scanf("%d%d%lld", &u, &v, &w);
      update(u, u, v, v, w);
    } else if (op == 2) {
      int u, l, r;
      scanf("%d%d%d%lld", &u, &l, &r, &w);
      update(u, u, l, r, w);
    } else if (op == 3) {
      int u, l, r;
      scanf("%d%d%d%lld", &u, &l, &r, &w);
      update(l, r, u, u, w);
    } else {
      puts("孙到");
    }
  }
  spafather(s);
  for (int i = 1; i <= n; ++i) {
    if (i == s) {
      printf("0 ");
      continue;
    }
    printf("%lld ", dis[rt2[i]] == Inf ? -1 : dis[rt2[i]]);
  }
}
