#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long INFF = 0x3f3f3f3f3f3f3f3fll;
const long long M = 1e9 + 7;
const long long maxn = 100007;
const double eps = 0.00000001;
long long gcd(long long a, long long b) { return b ? gcd(b, a % b) : a; }
template <typename T>
inline T abs(T a) {
  return a > 0 ? a : -a;
}
const int P = maxn * 4;
struct node {
  int n;
  long long d;
  node() {}
  node(int a, long long b) : n(a), d(b) {}
  const bool operator<(const node &a) const {
    if (d == a.d) return n < a.n;
    return d > a.d;
  }
};
vector<node> edge[maxn * 8];
long long dis[maxn * 8];
struct Tnode {
  int left, right;
} tree[maxn * 8];
void addedge(int u, int v, long long val) { edge[u].push_back(node(v, val)); }
void build(int x, int l, int r) {
  tree[x].left = l;
  tree[x].right = r;
  if (l == r) {
    addedge(x + P, x, 0);
    addedge(x, x + P, 0);
  } else if (l != r) {
    int mid = (l + r) / 2;
    build(x << 1, l, mid);
    addedge(x << 1, x, 0);
    addedge(x + P, (x << 1) + P, 0);
    build(x << 1 | 1, mid + 1, r);
    addedge(x << 1 | 1, x, 0);
    addedge(x + P, (x << 1 | 1) + P, 0);
  }
}
void add1(int x, int l, int r, int v, long long val) {
  int L = tree[x].left, R = tree[x].right;
  if (l <= L && R <= r) {
    addedge(v, x + P, val);
  } else {
    int mid = (L + R) / 2;
    if (mid >= l) add1(x << 1, l, r, v, val);
    if (r > mid) add1(x << 1 | 1, l, r, v, val);
  }
}
void add2(int x, int l, int r, int v, long long val) {
  int L = tree[x].left, R = tree[x].right;
  if (l <= L && R <= r) {
    addedge(x, v + P, val);
  } else {
    int mid = (L + R) / 2;
    if (mid >= l) add2(x << 1, l, r, v, val);
    if (r > mid) add2(x << 1 | 1, l, r, v, val);
  }
}
int find(int x, int i) {
  if (tree[x].left == tree[x].right) return x;
  int mid = (tree[x].left + tree[x].right) / 2;
  if (mid >= i)
    return find(x << 1, i);
  else
    return find(x << 1 | 1, i);
}
bool vis[maxn * 8];
void dijkstra(int s) {
  int i;
  priority_queue<node> Q;
  for (i = 0; i < maxn * 8; i++) dis[i] = INFF;
  dis[s] = 0;
  Q.push(node(s, 0));
  while (!Q.empty()) {
    node x = Q.top();
    Q.pop();
    if (vis[x.n]) continue;
    vis[x.n] = 1;
    for (i = 0; i < edge[x.n].size(); i++) {
      node y = edge[x.n][i];
      if (dis[y.n] > dis[x.n] + y.d) {
        dis[y.n] = dis[x.n] + y.d;
        Q.push(node(y.n, dis[y.n]));
      }
    }
  }
}
int n, m, s;
int i, j, k;
int l, r, u, v;
long long val;
int pos[maxn];
int main() {
  scanf("%d%d%d", &n, &m, &s);
  build(1, 1, n);
  for (i = 1; i <= n; i++) pos[i] = find(1, i);
  for (i = 0; i < m; i++) {
    scanf("%d", &k);
    if (k == 1) {
      scanf("%d%d%I64d", &v, &l, &val);
      add1(1, l, l, pos[v], val);
    } else if (k == 2) {
      scanf("%d%d%d%I64d", &v, &l, &r, &val);
      add1(1, l, r, pos[v], val);
    } else if (k == 3) {
      scanf("%d%d%d%I64d", &v, &l, &r, &val);
      add2(1, l, r, pos[v], val);
    }
  }
  dijkstra(pos[s]);
  for (i = 1; i <= n; i++) {
    if (dis[pos[i]] == INFF)
      printf("-1 ");
    else
      printf("%I64d ", dis[pos[i]]);
  }
}
