#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define inf 99264435330203ll
using namespace std;
long long read(){
	long long x=0,pos=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
	return pos?x:-x;
}
long long n,m,s,r1,r2;
const long long N = 2000001;
long long ls[N<<1],rs[N<<1],tot;
struct node{
	long long v,nex,w;
}edge[N<<1];
long long head[N<<1],top;
void add(long long u,long long v,long long w){
	edge[++top].v=v;
	edge[top].nex=head[u];
	edge[top].w=w;
	head[u]=top;
}
void build1(long long &now,long long l,long long r){
	if(l==r){
		now=l;
		return;
	}
	now=++tot;
	long long mid=(l+r)>>1;
	build1(ls[now],l,mid);
	build1(rs[now],mid+1,r);
	add(now,ls[now],0);
	add(now,rs[now],0);
}
void build2(long long &now,long long l,long long r){
	if(l==r){
		now=l;
		return;
	}
	now=++tot;
	long long mid=(l+r)>>1;
	build2(ls[now],l,mid);
	build2(rs[now],mid+1,r);
	add(ls[now],now,0);
	add(rs[now],now,0);
}
void modify1(long long now,long long l,long long r,long long ql,long long qr,long long u,long long w){
	if(ql<=l&&r<=qr){
		add(u,now,w);
		return;
	}
	long long mid=(l+r)>>1;
	if(ql<=mid) modify1(ls[now],l,mid,ql,qr,u,w);
	if(mid<qr) modify1(rs[now],mid+1,r,ql,qr,u,w);
}
void modify2(long long now,long long l,long long r,long long ql,long long qr,long long u,long long w){
	if(ql<=l&&r<=qr){
		add(now,u,w);
		return;
	}
	long long mid=(l+r)>>1;
	if(ql<=mid) modify2(ls[now],l,mid,ql,qr,u,w);
	if(mid<qr) modify2(rs[now],mid+1,r,ql,qr,u,w);
}
long long dis[N<<1],vis[N<<1];
struct tp{
	long long p,w;
};
struct cmp{
	bool operator()(tp a,tp b){
		return a.w<b.w;
	}
};
long long ans=0;
void dijkstra(long long s){
	priority_queue<tp,vector<tp>,cmp>q;
	for(long long i=1;i<=tot;i++){
		dis[i]=inf;vis[i]=0;
	}
	dis[s]=0;
	tp f;f.p=s;f.w=0;
	q.push(f);
	while(!q.empty()){
		long long now=q.top().p;q.pop();
		if(vis[now]) continue;vis[now]=1;
		for(long long i=head[now];i;i=edge[i].nex){
			long long v=edge[i].v;
			if(!vis[v]&&dis[v]>dis[now]+edge[i].w){
				dis[v]=dis[now]+edge[i].w;
				tp nw;nw.p=v,nw.w=dis[v];
				q.push(nw);
			}
		}
	}
	for(long long i=1;i<=n;i++){
		printf("%lld ",dis[i]>=inf?-1:dis[i]);
	}
}
int main(){
	n=read(),m=read(),s=read();
	tot=n;
	build1(r1,1,n);
	build2(r2,1,n);
	for(long long i=1;i<=m;i++){
		long long opt=read();
		if(opt==1){
			long long v=read(),u=read(),w=read();
			add(v,u,w);
		}else if(opt==2){
			long long v=read(),l=read(),r=read(),w=read();
			modify1(r1,1,n,l,r,v,w);
		}else{
			long long v=read(),l=read(),r=read(),w=read();
			modify2(r2,1,n,l,r,v,w);
		}
	}
	dijkstra(s);
	return 0;
}


#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
#define inf 99264435330203ll
using namespace std;
long long read(){
	long long x=0,pos=1;char ch=getchar();
	for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
	for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
	return pos?x:-x;
}
long long n,m,s,r1,r2;
const long long N = 500001;
long long ls[N<<1],rs[N<<1],tot;
struct node{
	long long v,nex,w;
}edge[N<<1];
long long head[N<<1],top;
void add(long long u,long long v,long long w){
	edge[++top].v=v;
	edge[top].nex=head[u];
	edge[top].w=w;
	head[u]=top;
}
void build1(long long &now,long long l,long long r){
	if(l==r){
		now=l;
		return;
	}
	now=++tot;
	long long mid=(l+r)>>1;
	build1(ls[now],l,mid);
	build1(rs[now],mid+1,r);
	add(now,ls[now],0);
	add(now,rs[now],0);
}
void build2(long long &now,long long l,long long r){
	if(l==r){
		now=l;
		return;
	}
	now=++tot;
	long long mid=(l+r)>>1;
	build2(ls[now],l,mid);
	build2(rs[now],mid+1,r);
	add(ls[now],now,0);
	add(rs[now],now,0);
}
void modify1(long long now,long long l,long long r,long long ql,long long qr,long long u,long long w){
	if(ql<=l&&r<=qr){
		add(u,now,w);
		return;
	}
	long long mid=(l+r)>>1;
	if(ql<=mid) modify1(ls[now],l,mid,ql,qr,u,w);
	if(mid<qr) modify1(rs[now],mid+1,r,ql,qr,u,w);
}
void modify2(long long now,long long l,long long r,long long ql,long long qr,long long u,long long w){
	if(ql<=l&&r<=qr){
		add(now,u,w);
		return;
	}
	long long mid=(l+r)>>1;
	if(ql<=mid) modify2(ls[now],l,mid,ql,qr,u,w);
	if(mid<qr) modify2(rs[now],mid+1,r,ql,qr,u,w);
}
long long dis[N<<1],vis[N<<1];
struct tp{
	long long p,w;
};
struct cmp{
	bool operator()(tp a,tp b){
		return a.w<b.w;
	}
};
long long ans=0;
void dijkstra(long long s){
	priority_queue<tp,vector<tp>,cmp>q;
	for(long long i=1;i<=tot;i++){
		dis[i]=inf;vis[i]=0;
	}
	dis[s]=0;
	tp f;f.p=s;f.w=0;
	q.push(f);
	while(!q.empty()){
		long long now=q.top().p;q.pop();
		if(vis[now]) continue;else vis[now]=1;
		for(long long i=head[now];i;i=edge[i].nex){
			long long v=edge[i].v;
			if(dis[v]>dis[now]+edge[i].w){
				dis[v]=dis[now]+edge[i].w;
				if(!vis[v]){
					tp nw;nw.p=v,nw.w=dis[v];
					q.push(nw);
				}
			}
		}
	}
	for(long long i=1;i<=n;i++){
		printf("%lld ",dis[i]==inf?-1:dis[i]);
	}
}
int main(){
	n=read(),m=read(),s=read();
	tot=n;
	build1(r1,1,n);
	build2(r2,1,n);
	for(long long i=1;i<=m;i++){
		long long opt=read();
		if(opt==1){
			long long v=read(),u=read(),w=read();
			add(v,u,w);
		}else if(opt==2){
			long long v=read(),l=read(),r=read(),w=read();
			modify1(r1,1,n,l,r,v,w);
		}else{
			long long v=read(),l=read(),r=read(),w=read();
			modify2(r2,1,n,l,r,v,w);
		}
	}
	dijkstra(s);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<6];
int fir[N<<4],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
void find(int p,int l,int r,int x,int y,vector<int> &now)
{
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return ;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	find(p<<1,l,mid,x,y,now);
	if(y>=mid+1)
	find(p<<1|1,mid+1,r,x,y,now);
	return ;
}
int dis[N<<4];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
bool vis[N<<4];
void dijkstra()
{
	for(int i=0;i<(N<<3);++i)
	dis[i]=1e18+7;
	vector<int> now;find(1,1,n,s,s,now);
	dis[now[0]]=0;
	q.push(make_pair(dis[now[0]],now[0]));
	while(!q.empty())
	{
		while(!q.empty()&&vis[q.top().second])
		q.pop();
		if(q.empty())
		break;
		pair<int,int> tmp=q.top();q.pop(),vis[tmp.second]=true;
		for(int i=fir[tmp.second];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>tmp.first+e[i].val)
			{
				dis[e[i].to]=tmp.first+e[i].val;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a;find(1,1,n,u,u,a);
			vector<int> b;find(1,1,n,v,v,b);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a;find(1,1,n,u,u,a);
			vector<int> b;find(1,1,n,l,r,b);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a;find(1,1,n,l,r,a);
			vector<int> b;find(1,1,n,v,v,b);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	dijkstra();
	for(int i=1;i<=n;++i)
	{
		vector<int> now;find(1,1,n,i,i,now);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5,M=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[(N<<3)+M];
int fir[N<<3],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<3];
queue<int> q;
bool vis[N<<3];
void spfa()
{
	for(int i=0;i<N<<3;++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(now[0]),vis[now[0]]=true;
	while(!q.empty())
	{
		int tmp=q.front();q.pop(),vis[tmp]=false;
		for(int i=fir[tmp];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>dis[tmp]+e[i].val)
			{
				dis[e[i].to]=dis[tmp]+e[i].val;
				if(!vis[e[i].to])
				q.push(e[i].to),vis[e[i].to]=true;
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	spfa();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<6];
int fir[N<<4],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<4];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
bool vis[N<<4];
void dijkstra()
{
	for(int i=0;i<(N<<3);++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(make_pair(dis[now[0]],now[0]));
	while(!q.empty())
	{
		while(!q.empty()&&vis[q.top().second])
		q.pop();
		if(q.empty())
		break;
		pair<int,int> tmp=q.top();q.pop(),vis[tmp.second]=true;
		for(int i=fir[tmp.second];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>tmp.first+e[i].val)
			{
				dis[e[i].to]=tmp.first+e[i].val;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	dijkstra();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<4];
int fir[N<<3],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<3];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
bool vis[N<<3];
void dijkstra()
{
	for(int i=0;i<(N<<3);++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(make_pair(dis[now[0]],now[0]));
	while(!q.empty())
	{
		while(!q.empty()&&vis[q.top().second])
		q.pop();
		if(q.empty())
		break;
		pair<int,int> tmp=q.top();q.pop(),vis[tmp.second]=true;
		for(int i=fir[tmp.second];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>tmp.first+e[i].val)
			{
				dis[e[i].to]=tmp.first+e[i].val;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	dijkstra();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<6];
int fir[N<<4],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<4];
priority_queue<pair<int,int>,vector<pair<int,int> >,greater<pair<int,int> > > q;
bool vis[N<<4];
void dijkstra()
{
	for(int i=0;i<(N<<3);++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(make_pair(dis[now[0]],now[0]));
	while(!q.empty())
	{
		while(!q.empty()&&vis[q.top().second])
		q.pop();
		if(q.empty())
		break;
		pair<int,int> tmp=q.top();q.pop(),vis[tmp.second]=true;
		for(int i=fir[tmp.second];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>tmp.first+e[i].val)
			{
				dis[e[i].to]=tmp.first+e[i].val;
				q.push(make_pair(dis[e[i].to],e[i].to));
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	dijkstra();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<4];
int fir[N<<3],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<3];
queue<int> q;
bool vis[N<<3];
void spfa()
{
	for(int i=0;i<N<<3;++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(now[0]),vis[now[0]]=true;
	while(!q.empty())
	{
		int tmp=q.front();q.pop(),vis[tmp]=false;
		for(int i=fir[tmp];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>dis[tmp]+e[i].val)
			{
				dis[e[i].to]=dis[tmp]+e[i].val;
				if(!vis[e[i].to])
				q.push(e[i].to),vis[e[i].to]=true;
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	spfa();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
int n,m,s;
int opt,u,v,l,r,w;
struct Edge{int nxt,to,val;}e[N<<4];
int fir[N<<3],size=0;
void add(int u,int v,int w)
{
	e[++size]=Edge{fir[u],v,w};
	fir[u]=size;
	return ;
}
void build(int p,int l,int r)
{
	if(l==r)
	{
		add(p+(N<<2),p,0);
		return ;
	}
	add(p<<1,p,0),add(p<<1|1,p,0);
	add(p+(N<<2),(p<<1)+(N<<2),0);
	add(p+(N<<2),(p<<1|1)+(N<<2),0);
	int mid=(l+r)>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	return ;
}
vector<int> find(int p,int l,int r,int x,int y)
{
	vector<int> now,tmp;
	now.clear();
	if(x<=l&&r<=y)
	{
		now.push_back(p);
		return now;
	}
	int mid=(l+r)>>1;
	if(x<=mid)
	{
		tmp=find(p<<1,l,mid,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	if(y>=mid+1)
	{
		tmp=find(p<<1|1,mid+1,r,x,y);
		for(int i=0;i<tmp.size();++i)
		now.push_back(tmp[i]);
	}
	return now;
}
int dis[N<<3];
queue<int> q;
bool vis[N<<3];
void spfa()
{
	for(int i=0;i<(N<<3);++i)
	dis[i]=1e18+7;
	vector<int> now=find(1,1,n,s,s);
	dis[now[0]]=0;
	q.push(now[0]),vis[now[0]]=true;
	while(!q.empty())
	{
		int tmp=q.front();q.pop(),vis[tmp]=false;
		for(int i=fir[tmp];i;i=e[i].nxt)
		{
			if(dis[e[i].to]>dis[tmp]+e[i].val)
			{
				dis[e[i].to]=dis[tmp]+e[i].val;
				if(!vis[e[i].to])
				q.push(e[i].to),vis[e[i].to]=true;
			}
		}
	}
	return ;
}
signed main()
{
	cin>>n>>m>>s;
	build(1,1,n);
	for(int i=1;i<=m;++i)
	{
		scanf("%lld",&opt);
		if(opt==1)
		{
			scanf("%lld%lld%lld",&u,&v,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,v,v);
			add(a[0],b[0]+(N<<2),w);
		}
		if(opt==2)
		{
			scanf("%lld%lld%lld%lld",&u,&l,&r,&w);
			vector<int> a=find(1,1,n,u,u);
			vector<int> b=find(1,1,n,l,r);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
		if(opt==3)
		{
			scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
			vector<int> a=find(1,1,n,l,r);
			vector<int> b=find(1,1,n,v,v);
			for(int i=0;i<a.size();++i)
			{
				for(int j=0;j<b.size();++j)
				add(a[i],b[j]+(N<<2),w);
			}
		}
	}
	spfa();
	for(int i=1;i<=n;++i)
	{
		vector<int> now=find(1,1,n,i,i);
		if(dis[now[0]]==1e18+7) printf("-1 ");
		else printf("%lld ",dis[now[0]]);
	}
	printf("\n");
	return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 2500001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        //DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M] , vis[M];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    //rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 100001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M << 1] , vis[M << 1];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 5000001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        //DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M] , vis[M];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    //rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 10000001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        //DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M] , vis[M];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    //rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 1000001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        //DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M] , vis[M];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    //rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include <algorithm>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <cstdlib>
#include <climits>
#include <cstdio>
#include <bitset>
#include <string>
#include <vector>
#include <cctype>
#include <stack>
#include <queue>
#include <deque>
#include <cmath>
#include <map>
#include <set>

#define I inline
#define fi first
#define se second
#define pb push_back
#define MP make_pair
#define PII pair<int , int>
#define PSL pair<string , long long>
#define PLL pair<long long , long long>
#define all(x) (x).begin() , (x).end()
#define copy(a , b) memcpy(a , b , sizeof(b))
#define clean(a , b) memset(a , b , sizeof(a))
#define rep(i , l , r) for (int i = (l); i <= (r); i ++)
#define per(i , r , l) for (int i = (r); i >= (l); i --)
#define PE(i , x) for(int i = head[x]; i; i = edge[i].last)
#define DEBUG(x) std :: cerr << #x << '=' << x << std :: endl

typedef long long ll;
typedef unsigned long long ull;

template <class T>
inline void read(T &x) {
    char c = getchar(), f = 0; x = 0;
    while (!isdigit(c)) f = (c == '-'), c = getchar();
    while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
    x = f ? -x : x;
}

using namespace std;

const int N = 10001;
const int M = 1000001;
const int HA = 998244353;

int n , q , s;

struct Edge{
	int to , last;
	ll dis;
}edge[M << 1];

int edge_num;
int head[M << 1];

I void add_edge(int from , int to , ll dis){
	edge[++ edge_num] = (Edge){to , head[from] , dis}; head[from] = edge_num;
}

namespace Segment_tree{
    #define lson(x) (x << 1)
    #define rson(x) (x << 1 | 1)

    struct Node{
        int l , r , len;
    }node[M << 2];

    void build(int x , int l , int r){
        node[x].l = l , node[x].r = r;
        node[x].len = (r - l + 1);
        if(l == r){
            add_edge(l + 8 * n , x , 0) , add_edge(x + 4 * n , l + 8 * n , 0);
            add_edge(x , l + 8 * n , 0) , add_edge(l + 8 * n , x + 4 * n , 0);
            return ;
        }
        int mid = (l + r) >> 1;
        add_edge(x , lson(x) , 0) , add_edge(lson(x) + 4 * n , x + 4 * n , 0);
        add_edge(x , rson(x) , 0) , add_edge(rson(x) + 4 * n , x + 4 * n , 0);
        build(lson(x) , l , mid) , build(rson(x) , mid + 1 , r);
    }

    void ADD_EDGE(int x , int ql , int qr , int type , int u , int w){
        if(ql == node[x].l && qr == node[x].r){
            if(type == 2){
                return add_edge(u + 8 * n , x , w);
            }
            else if(type == 3) return add_edge(x + 4 * n , u + 8 * n , w);
        }
        int mid = (node[x].l + node[x].r) >> 1;
        DEBUG(mid);
        if(qr <= mid){
            ADD_EDGE(lson(x) , ql , qr , type , u , w);
        }
        else if(ql > mid){
            ADD_EDGE(rson(x) , ql , qr , type , u , w);
        }
        else{
            ADD_EDGE(lson(x) , ql , mid , type , u , w);
            ADD_EDGE(rson(x) , mid + 1 , qr , type , u , w);
        }
    }

    #undef lson
    #undef rson
}

ll dis[M] , vis[M];

I void Dijkstra(int sta){
	priority_queue<PLL , vector<PLL> , greater<PLL> > Q;
	clean(dis , 0x3f3f3f3f) , clean(vis , 0);

	dis[sta] = 0;
	Q.push(MP(dis[sta] , sta));
	while(!Q.empty()){
		int fro = Q.top().se; Q.pop();
		if(vis[fro]) continue;
		vis[fro] = 1;
		PE(i , fro){
			int to = edge[i].to;
			if(dis[to] > dis[fro] + edge[i].dis){
				dis[to] = dis[fro] + edge[i].dis;
				Q.push(MP(dis[to] , to));
			}
		}
	}
}

using namespace Segment_tree;

int main() {
    #ifdef LOCAL
        freopen("try.in" , "r" , stdin);
        freopen("try1.out" , "w" , stdout);
    #endif
    read(n) , read(q) , read(s);
    build(1 , 1 , n);
    ll opt , l , r , u , v , w;
    rep(i , 1 , q){
        read(opt);
        if(opt == 1){
            read(u) , read(v) , read(w);
            u += 8 * n , v += 8 * n;
            add_edge(u , v , w);
        }
        else{
            read(v) , read(l) , read(r) , read(w);
            ADD_EDGE(1 , l , r , opt , v , w);
        }
    }
    s += 8 * n;

    Dijkstra(s);
    rep(i , 1 , 9 * n) DEBUG(dis[i]);
    rep(i , 1 , n){
        if(dis[i + 8 * n] == 4557430888798830399) printf("-1 ");
        else printf("%lld " , dis[i + 8 * n]);
    }

    return 0;
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[100004*22*3];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
list<node>lis[100004*22*3];
int n,qq,s,dis[100004*3],cnt,rt1,rt2;
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	lis[x].push_back((node){y,z});
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(auto it=lis[vii].begin();it!=lis[vii].end();it++)
		{
			if(dis[vii]+it->val<dis[it->v])
			{
				dis[it->v]=dis[vii]+it->val;
				q.push((node){it->v,dis[it->v]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[300002*20];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
//list<node>lis[100002*21*3];
int n,qq,s,dis[100002*3],cnt,rt1,rt2,tot,ver[100002*20],nex[100002*20],head[300002*20],edge[100002*21];
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	ver[++tot]=y,edge[tot]=z;
	nex[tot]=head[x],head[x]=tot;
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(int i=head[vii];i;i=nex[i])
		{
			if(dis[vii]+edge[i]<dis[ver[i]])
			{
				dis[ver[i]]=dis[vii]+edge[i];
				q.push((node){ver[i],dis[ver[i]]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int ls,rs;
}t[300002*20];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
//list<node>lis[100002*21*3];
int n,qq,s,dis[100002*3],cnt,rt1,rt2,tot,ver[100002*20],nex[100002*20],head[300002*20],edge[100002*21];
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	ver[++tot]=y,edge[tot]=z;
	nex[tot]=head[x],head[x]=tot;
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(int i=head[vii];i;i=nex[i])
		{
			if(dis[vii]+edge[i]<dis[ver[i]])
			{
				dis[ver[i]]=dis[vii]+edge[i];
				q.push((node){ver[i],dis[ver[i]]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[100002*21*3];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
//list<node>lis[100002*21*3];
int n,qq,s,dis[100002*3],cnt,rt1,rt2,tot,ver[100002*21],nex[100002*21],head[100002*21*3],edge[100002*21];
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	ver[++tot]=y,edge[tot]=z;
	nex[tot]=head[x],head[x]=tot;
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(int i=head[vii];i;i=nex[i])
		{
			if(dis[vii]+edge[i]<dis[ver[i]])
			{
				dis[ver[i]]=dis[vii]+edge[i];
				q.push((node){ver[i],dis[ver[i]]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[100004*21*2];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
list<node>lis[100004*21*2];
int n,qq,s,dis[100004*2],cnt,rt1,rt2;
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	lis[x].push_back((node){y,z});
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(auto it=lis[vii].begin();it!=lis[vii].end();it++)
		{
			if(dis[vii]+it->val<dis[it->v])
			{
				dis[it->v]=dis[vii]+it->val;
				q.push((node){it->v,dis[it->v]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[100002*21*3];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
list<node>lis[100002*21*3];
int n,qq,s,dis[100002*3],cnt,rt1,rt2;
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	lis[x].push_back((node){y,z});
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(auto it=lis[vii].begin();it!=lis[vii].end();it++)
		{
			if(dis[vii]+it->val<dis[it->v])
			{
				dis[it->v]=dis[vii]+it->val;
				q.push((node){it->v,dis[it->v]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<vector>
#include<cmath>
#include<map>
#include<string>
#include<queue>
#include<stack>
#include<bitset>
#include<list>
#include<set>
#include<utility>
#include<iomanip>
#define IO ios::sync_with_stdio(false)
#define eps 1e-7
#define int long long
using namespace std;
struct tre
{
	int l,r,ls,rs;
}t[100002*21*3];
struct node
{
	int v,val;
	bool operator < (const node &vv) const
	{
		return vv.val<val;
	}
};
//list<node>lis[100002*21*3];
int n,qq,s,dis[100002*3],cnt,rt1,rt2,tot,ver[100002*21*3],nex[100002*21*3],head[100002*21*3],edge[100002*21*3];
const int inf=0x3fffffffffffff;
priority_queue<node>q;
void adde(int x,int y,int z)
{
	ver[++tot]=y,edge[tot]=z;
	nex[tot]=head[x],head[x]=tot;
}
void buildin(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildin(t[o].ls,l,mid);
	buildin(t[o].rs,mid+1,r);
	adde(t[o].ls,o,0);
	adde(t[o].rs,o,0);
}
void buildout(int &o,int l,int r)
{
	if(l==r)
	{
		o=l;
		return;
	}
	o=++cnt;
	int mid=l+r>>1;
	buildout(t[o].ls,l,mid);
	buildout(t[o].rs,mid+1,r);
	adde(o,t[o].ls,0);
	adde(o,t[o].rs,0);
}
int L,R;
void upd(int o,int l,int r,int f,int val,int typ)
{
	if(L<=l&&R>=r)
	{
		if(typ==2)
		{
			adde(f,o,val);
		}
		else
		{
			adde(o,f,val);
		}
		return;
	}
	int mid=l+r>>1;
	if(L<=mid)
	{
		upd(t[o].ls,l,mid,f,val,typ);
	}
	if(R>mid)
	{
		upd(t[o].rs,mid+1,r,f,val,typ);
	}
}
signed main()
{
	IO;
	cin>>n>>qq>>s;
	cnt=n;
	buildout(rt1,1,n);
	buildin(rt2,1,n);
	for(int i=1;i<=qq;i++)
	{
		int op,f,t,val;
		cin>>op;
		if(op==1)
		{
			cin>>f>>t>>val;
			adde(f,t,val);
		}
		else if(op==2)
		{
			cin>>f>>L>>R>>val;
			upd(rt1,1,n,f,val,op);
		}
		else
		{
			cin>>f>>L>>R>>val;
			upd(rt2,1,n,f,val,op);
		}
	}
	for(int i=0;i<=100004*3-3;i++)
	{
		dis[i]=inf;
	}
	dis[s]=0;
	q.push((node){s,0});
	while(!q.empty())
	{
		int vii=q.top().v;
		if(-dis[vii]+q.top().val!=0)
		{
			q.pop();
			continue;
		}
		q.pop();
		for(int i=head[vii];i;i=nex[i])
		{
			if(dis[vii]+edge[i]<dis[ver[i]])
			{
				dis[ver[i]]=dis[vii]+edge[i];
				q.push((node){ver[i],dis[ver[i]]});
			}
		}
	}
	//cout<<inf<<endl;
	for(int i=1;i<=n;i++)
	{
		if(dis[i]<inf)
		{
			cout<<dis[i]<<" ";
		}
		else
		{
			cout<<"-1"<<" ";
		}
	}
}


#include<bits/stdc++.h>
#define N 100010
#define M 300010
#define LOG 20
typedef int mainint;
#define int long long
using namespace std;
int head[M],lc[M*LOG],rc[M*LOG],tot,ncnt;
int n,m,s,rt1,rt2;
struct Edge{
    int nxt,to,val;
    #define nxt(x) e[x].nxt
    #define to(x) e[x].to
    #define val(x) e[x].val
}e[N*LOG];
inline void addedge(int f,int t,int val){
    nxt(++tot)=head[f];to(tot)=t;val(tot)=val;head[f]=tot;
}
void buildOut(int &o,int l,int r){//建出树
    if(l==r){
        o=l;return;//已经是子节点,直接赋值
    }o=++ncnt;
    int mid=(l+r)>>1;
    buildOut(lc[o],l,mid);buildOut(rc[o],mid+1,r);
    addedge(o,lc[o],0);//从o向o的左右子树连一条权值为0的有向边
    addedge(o,rc[o],0);
}
void buildIn(int &o,int l,int r){//建入树
    if(l==r){
        o=l;return;
    }
    o=++ncnt;
    int mid=(l+r)>>1;
    buildIn(lc[o],l,mid);buildIn(rc[o],mid+1,r);
    addedge(lc[o],o,0);//从o向o的左右子树连一条权值为0的有向边
    addedge(rc[o],o,0);
}
int L,R;
void update(int o,int l,int r,int f,int val,short type){
    if(L<=l && R>=r){
        type==2?addedge(f,o,val):addedge(o,f,val);
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)update(lc[o],l,mid,f,val,type);
    if(R>mid)update(rc[o],mid+1,r,f,val,type);
}
const int inf=0x7fffffffffffffff;
int dis[M];
priority_queue< pair<int,int> > q;
int vis[M];
void dijkstra(int s){
    for(int i=1;i<=M;i++)dis[i]=inf,vis[i]=0;
    dis[s]=0;q.push(make_pair(0,s));
    while(q.size()){
        int x=q.top().second;q.pop();
        if(vis[x])continue;
        vis[x]=1;
        for(int i=head[x];i;i=nxt(i)){
            int y=to(i),z=val(i);
            if(!vis[y]&&dis[y]>dis[x]+z){
                dis[y]=dis[x]+z;
                q.push(make_pair(-dis[y],y));
            }
        }
    }
}
inline int read(){
    int data=0,w=1;char ch=0;
    while(ch!='-' && (ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')w=-1,ch=getchar();
    while(ch>='0' && ch<='9')data=data*10+ch-'0',ch=getchar();
    return data*w;
}
mainint main(){
    n=read();m=read();s=read();
    ncnt=n;//建边要求,线段树节点从n+1开始编号
    buildOut(rt1,1,n);buildIn(rt2,1,n);
    while(m--){
        int opt,f,t,val;
        opt=read();
        if(opt==1){
            f=read();t=read();val=read();
            addedge(f,t,val);//上面对叶子节点已经处理了,直接连边
        }else{
            f=read();L=read();R=read();val=read();
            update(opt==2?rt1:rt2,1,n,f,val,opt);
        }
    }
    dijkstra(s);
    for(int i=1;i<=n;i++)
        printf("%lld ",dis[i]<inf?dis[i]:-1);
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e15;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+7;
long long node_num;
struct T{
    int l;
    int r;
    vector<int> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    int index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
int id[MAXN];//用来对应编号和每个点的index
void build(int tmp,int l,int r){
    node_num++;
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+4*MAXN].l=l;
    tree[tmp+4*MAXN].r=r;
    int mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+4*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+4*MAXN].g.push_back(tmp);
        tree[tmp+4*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+4*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+1+4*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
}
int n,s,Q;
void add1(int tmp,int l,int r,int val,int temp,int order){
    int L=tree[tmp].l;
    int R=tree[tmp].r;
    int mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+4*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+4*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+4*MAXN].cost=1e15;
        dis[i+4*MAXN].index=i+4*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&Q,&s);
    build(1,1,n);
    int ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%d%d%d%d",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+4*MAXN]);
            tree[id[ch2]].v.push_back(id[ch4]);
        }
        else if(ch1==2){
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp+3*MAXN].g.push_back(temp);
            tree[tmp+3*MAXN].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e15;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
long long node_num;
struct T{
    int l;
    int r;
    vector<int> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    int index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
int id[MAXN];//用来对应编号和每个点的index
void build(int tmp,int l,int r){
    node_num++;
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+4*MAXN].l=l;
    tree[tmp+4*MAXN].r=r;
    int mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+4*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+4*MAXN].g.push_back(tmp);
        tree[tmp+4*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+4*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+1+4*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
}
int n,s,Q;
void add1(int tmp,int l,int r,int val,int temp,int order){
    int L=tree[tmp].l;
    int R=tree[tmp].r;
    int mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+4*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+4*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+4*MAXN].cost=1e15;
        dis[i+4*MAXN].index=i+4*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&Q,&s);
    build(1,1,n);
    int ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%d%d%d%d",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+4*MAXN]);
            tree[id[ch2]].v.push_back(id[ch4]);
        }
        else if(ch1==2){
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+7;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num++;
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e15;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(id[ch4]);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
第一颗树是连出边的，第二课树是连入边的
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=MAXN*4;++i){
        dis[i].cost=1e18;
        dis[i].index=i;
        // dis[i+3*MAXN].cost=1e18;
        // dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(dis[id[i]].cost==1e18)printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
第一颗树是连出边的，第二课树是连入边的
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=MAXN*4;++i){
        dis[i].cost=1e18;
        dis[i].index=i;
        // dis[i+3*MAXN].cost=1e18;
        // dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(dis[id[i]].cost==1e18&&dis[id[i]+3*MAXN].cost==1e18)printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
第一颗树是连出边的，第二课树是连入边的
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=MAXN;++i){
        dis[i].cost=1e18;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e18;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        // if(mark[bg.index]) continue;
        // mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(dis[id[i]].cost==1e18)printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+7;
long long node_num;
struct T{
    int l;
    int r;
    vector<int> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    int index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
int id[MAXN];//用来对应编号和每个点的index
void build(int tmp,int l,int r){
    node_num++;
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    int mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
int n,s,Q;
void add1(int tmp,int l,int r,int val,int temp,int order){
    int L=tree[tmp].l;
    int R=tree[tmp].r;
    int mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e15;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&Q,&s);
    build(1,1,n);
    int ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%d%d%d%d",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(id[ch4]);
        }
        else if(ch1==2){
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%d",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


#include<bits/stdc++.h>
using namespace std;
const int MAXN=3e5+7;
long long node_num;
struct T{
    long long l;
    long long r;
    vector<long long> g,v;
}tree[MAXN*8];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条0边
跑最短路的时候就是直接从第二课树开始跑
又由于两棵树的编号是一样的，到时候直接加入就好了
*/
struct D{
    long long index;
    long long cost;
}dis[MAXN*8];
struct large{
    bool operator()(D x,D y){
        return x.cost>y.cost;
    }
};
long long id[MAXN];//用来对应编号和每个点的index
void build(long long tmp,long long l,long long r){
    node_num=max(node_num,tmp);
    tree[tmp].l=l;                                       //0是出，1是入
    tree[tmp].r=r;
    tree[tmp+3*MAXN].l=l;
    tree[tmp+3*MAXN].r=r;
    long long mid=(l+r)>>1;
    if(l==r){
        id[l]=tmp;
        tree[tmp].g.push_back(tmp+3*MAXN);
        tree[tmp].v.push_back(0);
        tree[tmp+3*MAXN].g.push_back(tmp);
        tree[tmp+3*MAXN].v.push_back(0);
        return;
    }
    build(tmp*2,l,mid);
    tree[tmp*2].g.push_back(tmp);
    tree[tmp*2].v.push_back(0);
    tree[tmp+4*MAXN].g.push_back(tmp*2+3*MAXN);
    tree[tmp+4*MAXN].v.push_back(0);
    build(tmp*2+1,mid+1,r);
    tree[tmp*2+1].g.push_back(tmp);
    tree[tmp*2+1].v.push_back(0);
    tree[tmp+3*MAXN].g.push_back(tmp*2+1+3*MAXN);
    tree[tmp+3*MAXN].v.push_back(0);
}
long long n,s,Q;
void add1(long long tmp,long long l,long long r,long long val,long long temp,long long order){
    long long L=tree[tmp].l;
    long long R=tree[tmp].r;
    long long mid=(L+R)>>1;
    if(L==l&&R==r){
        if(order==1){
            tree[temp].g.push_back(tmp+3*MAXN);
            tree[temp].v.push_back(val);
        }
        else{
            tree[tmp].g.push_back(temp+3*MAXN);
            tree[tmp].v.push_back(val);
        }
        return;
    }
    if(r<=mid) add1(tmp*2,l,r,val,temp,order);
    else if(l>mid) add1(tmp*2+1,l,r,val,temp,order);
    else{
        add1(tmp*2,l,mid,val,temp,order);
        add1(tmp*2+1,mid+1,r,val,temp,order);
    }
}
int mark[8*MAXN];
priority_queue<D,vector<D>,large> q;
void dij(){
    for(int i=1;i<=node_num;++i){
        dis[i].cost=1e15;
        dis[i].index=i;
        dis[i+3*MAXN].cost=1e15;
        dis[i+3*MAXN].index=i+3*MAXN;
    }
    dis[id[s]].cost=0;
    q.push(dis[id[s]]);
    D bg;
    while(!q.empty()){
        bg=q.top();
        q.pop();
        if(mark[bg.index]) continue;
        mark[bg.index]=1;
        for(int i=0;i<tree[bg.index].g.size();++i){
            if(dis[tree[bg.index].g[i]].cost>dis[bg.index].cost+tree[bg.index].v[i]){
                dis[tree[bg.index].g[i]].cost=dis[bg.index].cost+tree[bg.index].v[i];
                q.push(dis[tree[bg.index].g[i]]);
            }
        }
    }
}
int main(){
    scanf("%lld%lld%lld",&n,&Q,&s);
    build(1,1,n);
    long long ch1,ch2,ch3,ch4,ch5;
    while(Q--){
        scanf("%lld%lld%lld%lld",&ch1,&ch2,&ch3,&ch4);
        if(ch1==1){
            tree[id[ch2]].g.push_back(id[ch3+3*MAXN]);
            tree[id[ch2]].v.push_back(ch4);
        }
        else if(ch1==2){
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],1);
        }
        else{
            scanf("%lld",&ch5);
            add1(1,ch3,ch4,ch5,id[ch2],2);
        }
    }
    dij();
    for(int i=1;i<=n;++i){
        if(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}