#include <bits/stdc++.h>
using namespace std;
void RI() {}
template <typename... T>
void RI(int& head, T&... tail) {
  scanf("%d", &head);
  RI(tail...);
}
void PI() { putchar('\n'); }
template <typename... T>
void PI(const int head, T... tail) {
  printf("%d ", head);
  PI(tail...);
}
struct edge {
  int to, cost;
};
const long long INF = LLONG_MAX;
int V;
vector<edge> G[5 * 200003];
long long d[5 * 200003];
void dijkstra(int s) {
  priority_queue<pair<int, int>, vector<pair<int, int> >,
                 greater<pair<int, int> > >
      que;
  fill(d, d + V, INF);
  d[s] = 0;
  que.push(make_pair(0, s));
  while (!que.empty()) {
    pair<int, int> p = que.top();
    que.pop();
    int v = p.second;
    if (d[v] < p.first) continue;
    for (int i = 0; i < (int)G[v].size(); i++) {
      edge e = G[v][i];
      if (d[e.to] > d[v] + e.cost) {
        d[e.to] = d[v] + e.cost;
        que.push(make_pair(d[e.to], e.to));
      }
    }
  }
}
int n, q, s;
int offset;
inline int segt0(int i) { return i; }
inline int segt1(int i) { return i + offset; }
inline int vtx(int p) { return p + 2 * offset; }
void build() {
  for (int i = 0; i < (int)(n); i++) {
    int p = i + n;
    G[vtx(i)].push_back(edge{segt0(p), 0});
    G[segt1(p)].push_back(edge{vtx(i), 0});
    for (; p > 1; p >>= 1) {
      G[vtx(i)].push_back(edge{segt0(p >> 1), 0});
      G[segt1(p >> 1)].push_back(edge{vtx(i), 0});
    }
  }
}
void query(int l, int r, int type, int v, int w) {
  for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
    if (l & 1) {
      if (type == 1 or type == 2) {
        G[vtx(v)].push_back(edge{segt1(l++), w});
      } else {
        G[segt0(l++)].push_back(edge{vtx(v), w});
      }
    }
    if (r & 1) {
      if (type == 1 or type == 2) {
        G[vtx(v)].push_back(edge{segt1(--r), w});
      } else {
        G[segt0(--r)].push_back(edge{vtx(v), w});
      }
    }
  }
}
void M1() {}
template <typename... T>
void M1(int& head, T&... tail) {
  head -= 1;
  M1(tail...);
}
int main() {
  RI(n, q, s);
  M1(s);
  offset = 1;
  while (offset < n * 2) {
    offset *= 2;
  }
  V = 2 * offset + n;
  build();
  int type, v, w, l, r;
  for (int i = 0; i < (int)(q); i++) {
    RI(type);
    if (type == 1) {
      RI(v, l, w);
      M1(v, l);
      query(l, l + 1, type, v, w);
    } else if (type == 2 or type == 3) {
      RI(v, l, r, w);
      M1(v, l, r);
      query(l, r + 1, type, v, w);
    }
  }
  dijkstra(vtx(s));
  for (int i = 0; i < (int)(n); i++) {
    if (d[vtx(i)] == INF)
      printf("%d ", -1);
    else
      printf("%lld ", d[vtx(i)]);
  }
  putchar('\n');
  return 0;
}
