#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define root 1,n,1
#define ls rt<<1
#define rs rt<<1|1
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
inline ll read() {
ll x=0,w=1;char ch=getchar();
for(;ch>'9'||ch<'0';ch=getchar()) if(ch=='-') w=-1;
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*w;
}
inline void print(__int128 x){
if(x<0) {putchar('-');x=-x;}
if(x>9) print(x/10);
putchar(x%10+'0');
}
#define maxn 1000000
const double eps=1e-8;
#define int_INF 0x3f3f3f3f
#define ll_INF 0x3f3f3f3f3f3f3f3f
vector<pair<int,ll> >edge[maxn];int in_leaf[maxn],out_leaf[maxn];
namespace OUT_TREE{
struct Segment_tree{
int l,r;
}tree[maxn<<2];
void build(int l,int r,int rt) {
tree[rt].l=l;tree[rt].r=r;
if(l==r) {
out_leaf[l]=rt;
return ;
}
int mid=(l+r)>>1;
build(lson);build(rson);
edge[rt].push_back({ls,0});
edge[rt].push_back({rs,0});
}
void update(int l,int r,int rt,int pos,int val) {
if(tree[rt].l==l&&tree[rt].r==r) {
edge[pos].push_back({rt,val});
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(r<=mid) update(l,r,ls,pos,val);
else if(l>mid) update(l,r,rs,pos,val);
else update(l,mid,ls,pos,val),update(mid+1,r,rs,pos,val);
}
}
namespace IN_TREE{
int BASE=5e5;
struct Segment_tree{
int l,r;
}tree[maxn<<2];
void build(int l,int r,int rt) {
tree[rt].l=l;tree[rt].r=r;
if(l==r) {
in_leaf[l]=rt+BASE;
return ;
}
int mid=(l+r)>>1;
build(lson);build(rson);
edge[ls+BASE].push_back({rt+BASE,0});
edge[rs+BASE].push_back({rt+BASE,0});
}
void update(int l,int r,int rt,int pos,int val) {
if(tree[rt].l==l&&tree[rt].r==r) {
edge[rt+BASE].push_back({pos,val});
return ;
}
int mid=(tree[rt].l+tree[rt].r)>>1;
if(r<=mid) update(l,r,ls,pos,val);
else if(l>mid) update(l,r,rs,pos,val);
else update(l,mid,ls,pos,val),update(mid+1,r,rs,pos,val);
}
}
struct heapnode{
ll u,dis;
bool operator < (const heapnode &rhs) const {
return dis>rhs.dis;
}
};
ll dis[maxn],vis[maxn];
void dij(int s) {
priority_queue<heapnode>q;
memset(dis,0x3f,sizeof dis);memset(vis,0,sizeof vis);
q.push({s,0});dis[s]=0;
while(!q.empty()) {
heapnode f=q.top();q.pop();
int u=f.u;
if(vis[u]) continue;
vis[u]=1;
for(auto [v,d]:edge[u]) {
if(dis[v]>dis[u]+d) {
dis[v]=dis[u]+d;
q.push({v,dis[v]});
}
}
}
}
int main() {
int n=read();int q=read();int s=read();
OUT_TREE::build(1,n,1);IN_TREE::build(1,n,1);
for(int i=1;i<=n;i++) {
edge[out_leaf[i]].push_back({in_leaf[i],0});
edge[in_leaf[i]].push_back({out_leaf[i],0});
}
for(int i=1;i<=q;i++) {
int opt=read();
if(opt==1) {
int u=read();int v=read();int w=read();
edge[out_leaf[u]].push_back({in_leaf[v],w});
edge[in_leaf[u]].push_back({out_leaf[v],w});
}
else if(opt==2) {
int u=read();int l=read();int r=read();int w=read();
OUT_TREE::update(l,r,1,in_leaf[u],w);
}
else {
int u=read();int l=read();int r=read();int w=read();
IN_TREE::update(l,r,1,out_leaf[u],w);
}
}
dij(out_leaf[s]);
for(int i=1;i<=n;i++) {
if(dis[out_leaf[i]]==ll_INF) cout<<-1<<" ";
else cout<<dis[out_leaf[i]]<<" ";
}
return 0;
}