#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+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("%d%d%d",&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("%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];
/*
第一颗树是连出边的，第二课树是连入边的
*/
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=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];
/*
有两颗线段树
其中一颗是作为一个是连向外边，自下而上连出去的
另一颗是自外向内连进来，每个父亲到儿子都有一条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=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(!mark[id[i]])printf("-1 ");
        else printf("%lld ",dis[id[i]].cost);
    }
}


# include <bits/stdc++.h>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1) + 42];

int head[N + 42],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(++tot,++tot);
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int opt,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(opt == 1) add_edge(x,t[K].Down);
        else add_edge(t[K].Up,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,opt,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,opt,mid+1,R,Rs(K));
    }
}

void Input()
{
    tot = (n = Read());
    int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            Modify(l,r,tot,1,1,n,1);
        }
        else
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    for(int i = 1; i <= n ; ++i) printf("%d ",dis[i] == INF ? -1 : dis[i]);
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <queue>
# include <cstdio>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1)+5];

int head[N+5],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(tot+1,tot+2);
        tot += 2;
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int op,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(op == 1) add_edge(x,t[K].Down);
        else if(op == 2) add_edge(t[K].Up,x);
        //printf("op = %d L = %d R = %d x = %d \n",op,L,R,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,op,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,op,mid+1,R,Rs(K));
    }
}

void Input()
{
    n = Read();
    tot = n;
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
            //printf("edge case %d,opt %d:%d %d %d\n",q,opt,l,r,e[edge_tot].wi);
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,1,1,n,1);
        }
        else if(opt == 3)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    /*for(int i = 1; i <= tot ; ++i)
    {
        printf("case%d:",i);
        for(int j = head[i]; j ; j = e[j].Next) printf("%d ",e[j].to);
        puts("");
    }*/

    for(int i = 1; i <= n ; ++i) printf("%d ",((dis[i] == INF) ? -1 : dis[i]));
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <queue>
# include <cstdio>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc (SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<3)+5];

int head[N+5],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(tot+1,tot+2);
        tot += 2;
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int op,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(op == 1) add_edge(x,t[K].Down);
        else if(op == 2) add_edge(t[K].Up,x);
        //printf("op = %d L = %d R = %d x = %d \n",op,L,R,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,op,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,op,mid+1,R,Rs(K));
    }
}

void Input()
{
    n = Read();
    tot = n;
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
            //printf("edge case %d,opt %d:%d %d %d\n",q,opt,l,r,e[edge_tot].wi);
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,1,1,n,1);
        }
        else if(opt == 3)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    /*for(int i = 1; i <= tot ; ++i)
    {
        printf("case%d:",i);
        for(int j = head[i]; j ; j = e[j].Next) printf("%d ",e[j].to);
        puts("");
    }*/

    for(int i = 1; i <= n ; ++i) printf("%lld ",((dis[i] == INF) ? -1 : dis[i]));
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <queue>
# include <cstdio>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1)+5];

int head[N+5],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(tot+1,tot+2);
        tot += 2;
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int op,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(op == 1) add_edge(x,t[K].Down);
        else if(op == 2) add_edge(t[K].Up,x);
        //printf("op = %d L = %d R = %d x = %d \n",op,L,R,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,op,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,op,mid+1,R,Rs(K));
    }
}

void Input()
{
    n = Read();
    tot = n;
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
            //printf("edge case %d,opt %d:%d %d %d\n",q,opt,l,r,e[edge_tot].wi);
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,1,1,n,1);
        }
        else if(opt == 3)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            //printf("edge case %d,opt %d:%d %d %d %d\n",q,opt,v,l,r,e[edge_tot].wi);
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    /*for(int i = 1; i <= tot ; ++i)
    {
        printf("case%d:",i);
        for(int j = head[i]; j ; j = e[j].Next) printf("%d ",e[j].to);
        puts("");
    }*/

    for(int i = 1; i <= n ; ++i) printf("%lld ",((dis[i] == INF) ? -1 : dis[i]));
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <queue>
# include <cstdio>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1)+5];

int head[N+5],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(++tot,++tot);
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int opt,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(opt == 1) add_edge(x,t[K].Down);
        else add_edge(t[K].Up,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,opt,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,opt,mid+1,R,Rs(K));
    }
}

void Input()
{
    n = Read();
    tot = n;
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            Modify(l,r,tot,1,1,n,1);
        }
        else
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    for(int i = 1; i <= n ; ++i) printf("%d ",dis[i] == INF ? -1 : dis[i]);
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <bits/stdc++.h>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1) + 42];

int head[N + 42],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(++tot,++tot);
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int opt,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(opt == 1) add_edge(x,t[K].Down);
        else add_edge(t[K].Up,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,opt,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,opt,mid+1,R,Rs(K));
    }
}

void Input()
{
    tot = (n = Read());
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            Modify(l,r,tot,1,1,n,1);
        }
        else
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    for(int i = 1; i <= n ; ++i) printf("%d ",dis[i] == INF ? -1 : dis[i]);
}

int main()
{
    //freopen("ysqm.in","r",stdin);
    Solve();
    return 0;
}


# include <bits/stdc++.h>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc getchar()//(SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1)+5];

int head[N+5],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(++tot,++tot);
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int opt,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(opt == 1) add_edge(x,t[K].Down);
        else add_edge(t[K].Up,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,opt,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,opt,mid+1,R,Rs(K));
    }
}

void Input()
{
    n = Read();
    tot = n;
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            Modify(l,r,tot,1,1,n,1);
        }
        else
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    while(q.size()) q.pop();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    for(int i = 1; i <= n ; ++i) printf("%d ",dis[i] == INF ? -1 : dis[i]);
}

int main(){Solve();return 0;}


# include <bits/stdc++.h>
# define reg register
# define N 500000
# define INF 0x3f3f3f3f3f3f3f3f
# define Ls(K) (K<<1)
# define Rs(K) (K<<1|1)
# define Gc (SS == TT && (TT = (SS = BB) + fread(BB,1,1 << 15,stdin),TT == SS) ? EOF : *SS++)
char BB[1<<15],*SS=BB,*TT=BB;
inline int Read()
{
    register int x = 0;char ch = Gc;

    while(ch < '0' || ch > '9')ch = Gc;

    while(ch >= '0' && ch <= '9'){x = x*10+(ch^48);ch = Gc;}

    return x;
}

struct edge
{
    int Next,to,wi;

    edge(const int Next_=0,const int To_=0,const int wi_=0):Next(Next_),to(To_),wi(wi_){}
} e[(N<<1) + 42];

int head[N + 42],edge_tot = 1;

inline void add_edge(const int u,const int v,const int wi=0)
{
    e[++edge_tot] = edge(head[u],v,wi);

    head[u] = edge_tot;
}

struct Seg
{
    int Up,Down;
    Seg(const int Up_=0,const int Down_=0):Up(Up_),Down(Down_){}
} t[N+5];

long long dis[N+5];
int n,s,tot;

void Build(const int L,const int R,const int K)
{
    if(L == R) t[K] = Seg(L,L);
    else
    {
        t[K] = Seg(++tot,++tot);
        int mid = (L+R)>>1;
        Build(L,mid,Ls(K));
        Build(mid+1,R,Rs(K));
        add_edge(t[K].Down,t[Ls(K)].Down);
        add_edge(t[K].Down,t[Rs(K)].Down);
        add_edge(t[Ls(K)].Up,t[K].Up);
        add_edge(t[Rs(K)].Up,t[K].Up);
    }
}

void Modify(const int AL,const int AR,const int x,const int opt,const int L,const int R,const int K)
{
    if(AL <= L && R <= AR)
    {
        if(opt == 1) add_edge(x,t[K].Down);
        else add_edge(t[K].Up,x);
    }
    else
    {
        int mid = (L+R)>>1;
        if(AL <= mid) Modify(AL,AR,x,opt,L,mid,Ls(K));
        if(AR > mid) Modify(AL,AR,x,opt,mid+1,R,Rs(K));
    }
}

void Input()
{
    tot = (n = Read());
    register int v,l,r,w,opt,q = Read();s = Read();
    Build(1,n,1);
    while(q--)
    {
        opt = Read();
        if(opt == 1)
        {
            l = Read();r = Read();
            add_edge(l,r,Read());
        }
        else if(opt == 2)
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(v,tot,Read());
            Modify(l,r,tot,1,1,n,1);
        }
        else
        {
            v = Read();l = Read();r = Read();++tot;
            add_edge(tot,v,Read());
            Modify(l,r,tot,2,1,n,1);
        }
    }
}

bool inq[N+5];

void Solve()
{
    std::queue<int> q;
    Input();
    for(int i = 1; i <= tot; ++i) dis[i] = INF;
    q.push(s);inq[s] = 1;dis[s] = 0;
    while(q.size())
    {
        int u = q.front();q.pop();inq[u] = 0;
        for(int i = head[u]; i ; i = e[i].Next)
            if(dis[e[i].to] > dis[u]+e[i].wi)
            {
                dis[e[i].to] = dis[u]+e[i].wi;
                if(!inq[e[i].to]){inq[e[i].to] = 1;q.push(e[i].to);}
            }
    }
    for(int i = 1; i <= n ; ++i) printf("%d ",dis[i] == INF ? -1 : dis[i]);
}

int main(){Solve();return 0;}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int tot = 0;

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    int id;
    void init() {
        id = ++tot;
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): end(end), cost(cost) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 10000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[4*MAXN];
Vertex tarT[4*MAXN];
///

void expand(vector<Vertex *> &res, int l, int r, Vertex *root, int i, int tl, int tr) {
    if (r < tl || l > tr) return;
    if (l <= tl && r >= tr) res.push_back(root+i);
    else {
        int tm = (tl+tr)/2;
        expand(res,l,r,root,2*i+1,tl,tm);
        expand(res,l,r,root,2*i+2,tm+1,tr);
    }
}

void adjoin(int sl, int sr, int tl, int tr, int cost) {
    vector<Vertex *> sv,tv;
    expand(sv,sl,sr,srcT,0,1,n);
    expand(tv,tl,tr,tarT,0,1,n);
    for (int i=0; i<sv.size(); i++) for (int j=0; j<tv.size(); j++) {
        err("Edge %d->%d (cost %d)\n",sv[i]->id,tv[j]->id,cost);
        sv[i]->out.push_back( Path(tv[j],cost) );
    }
}

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u; ll w; cin >> u >> w;
            adjoin(v,v,u,u,w);
        } else {
            int l,r; ll w; cin >> l >> r >> w;
            if (t==2) adjoin(v,v,l,r,w);
            else adjoin(l,r,v,v,w);
        }
    }

    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path cu = pq.top(); pq.pop();
        if (cu.end->cost != -1) continue;
        cu.end->cost = cu.cost;
        for (int i=0; i<cu.end->out.size(); i++) {
            Path nx(cu.end->out[i].end, cu.cost + cu.end->out[i].cost);
            pq.push(nx);
        }
    }
    for (int i=1; i<=n; i++) {
        cout << planet[i].cost << " ";
    }
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=n; i++) planet[i].init();
    for (int i=0; i<4*n; i++) {
        srcT[i].init();
        tarT[i].init();
        if (i != 0) {
            int j = (i-1)/2;
            srcT[i].out.push_back( Path(srcT+j,0) );
            tarT[j].out.push_back( Path(tarT+i,0) );
        }
    }
    for (int i=1; i<=n; i++) {
        vector<Vertex *> ss,tt;
        expand(ss,i,i,srcT,0,1,n); expand(tt,i,i,tarT,0,1,n);
        planet[i].out.push_back( Path( ss[0], 0));
        tt[0]->out.push_back(Path(planet+i,0));
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    void init() {
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): cost(cost), end(end) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[2*MAXN+2];
Vertex tarT[2*MAXN+2];
///

int parent(int i) {
    if (i == (i&-i) && 2*i > 2*n+1) return 0; // Root
    int j = i;
    do {
        int d = j&-j;
        j = (j ^ d) | (d<<1);
    } while (j > 2*n+1);
    return j;
}

void link(Vertex *a, Vertex *b, int cost) {
    a->out.push_back(Path(b,cost));
}

struct Parts {
    Vertex *root;
    int l;
    int r;
    Parts(Vertex *root, int l, int r): root(root), l(l), r(r) {}
    Vertex *next() {
        assert(l <= r);
        if (l == r) return NULL;
        int index;
        int d = l&-l;
        if (l+d <= r) {
            index = (2*l+d);
            l += d;
        } else {
            d = r&-r;
            r -= d;
            index = (2*r+d);
        }
        while (index > 2*n+1) index = parent(index);
        return root + index;
    }
};

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u,w; cin >> u >> w;
            link(planet+v,planet+u,w);
        } else {
            int r,l,w; cin >> l >> r >> w;
            Vertex *u;
            if (t==2) {
                Parts p(tarT,l,r+1);
                while ((u = p.next()) != NULL) link(planet+v,u,w);
            } else {
                Parts p(srcT,l,r+1);
                while ((u = p.next()) != NULL) link(u,planet+v,w);
            }
        }
    }
    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path p = pq.top(); pq.pop();
        if (p.end->cost != -1) continue;
        p.end->cost = p.cost;
        for (int i=0; i<p.end->out.size(); i++) {
            pq.push( Path(p.end->out[i].end, p.cost + p.end->out[i].cost) );
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=2*n+1; i++) {
        srcT[i].init();
        tarT[i].init();
        int j = parent(i);
        if (j) {
            link(srcT+i,srcT+j,0);
            link(tarT+j,tarT+i,0);
        }
    }
    for (int i=1; i<=n; i++) {
        planet[i].init();
        link(planet+i,srcT+2*i+1,0);
        link(tarT+2*i+1,planet+i,0);
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    string name;
    void init() {
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): cost(cost), end(end) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[2*MAXN+2];
Vertex tarT[2*MAXN+2];
///

int parent(int i) {
    if (i == (i&-i) && 2*i > 2*n+1) return 0; // Root
    int j = i;
    do {
        int d = j&-j;
        j = (j ^ d) | (d<<1);
    } while (j > 2*n+1);
    return j;
}

void link(Vertex *a, Vertex *b, int cost) {
    //err("Edge: (%s) -> (%s) cost %d\n",a->name.c_str(),b->name.c_str(),cost);
    a->out.push_back(Path(b,cost));
}

struct Parts {
    Vertex *root;
    int l;
    int r;
    Parts(Vertex *root, int l, int r): root(root), l(l), r(r) {}
    Vertex *next() {
        assert(l <= r);
        if (l == r) return NULL;
        int index;
        int d = l&-l;
        if (l+d <= r) {
            index = (2*l+d);
            l = min(l+d,n+1);
        } else {
            do {d >>= 1;} while (!(d&r));
            index = (2*l+d);
            l += d;
        }
        while (index > 2*n+1) index = parent(index);
        //err("[%d,%d)...",(index - (index&-index))/2,(index+(index&-index))/2);
        return root + index;
    }
};

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u,w; cin >> u >> w;
            link(planet+v,planet+u,w);
        } else {
            int r,l,w; cin >> l >> r >> w;
            Vertex *u;
            //err("breaking up [%d,%d): ",l,r+1);
            if (t==2) {
                Parts p(tarT,l,r+1);
                while ((u = p.next()) != NULL) link(planet+v,u,w);
                //err("\n");
            } else {
                Parts p(srcT,l,r+1);
                while ((u = p.next()) != NULL) link(u,planet+v,w);
                //err("\n");
            }
        }
    }
    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path p = pq.top(); pq.pop();
        if (p.end->cost != -1) continue;
        //err("Let's visit (%s)\n",p.end->name.c_str());
        p.end->cost = p.cost;
        for (int i=0; i<p.end->out.size(); i++) {
            pq.push( Path(p.end->out[i].end, p.cost + p.end->out[i].cost) );
            //err("--found a route to (%s)\n",p.end->out[i].end->name.c_str());
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    if (!cin.good()) return false;
    for (int i=1; i<=2*n+1; i++) {
        string suff = "[" + to_string((i-(i&-i))/2) + "," + to_string(min(n,(i+(i&-i))/2-1)) + "]";
        srcT[i].name = "SRC-" + suff;
        tarT[i].name = "TAR-" + suff;
    }
    for (int i=1; i<=2*n+1; i++) {
        srcT[i].init();
        tarT[i].init();
    }
    for (int i=1; i<=2*n+1; i++) {
        int j = parent(i);
        if (j) {
            link(srcT+i,srcT+j,0);
            link(tarT+j,tarT+i,0);
            //err("Parent of [%d,%d] is [%d,%d]\n",(i-(i&-i))/2,(i+(i&-i))/2-1,(j-(j&-j))/2,(j+(j&-j))/2-1);
        }
    }
    for (int i=1; i<=n; i++) {
        planet[i].init();
        planet[i].name = "PLANET-" + to_string(i);
        link(planet+i,srcT+(2*i+1),0);
        link(tarT+(2*i+1),planet+i,0);
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int n,q,s;
struct Edge;
struct Vertex {
    string name;
    vector<Edge> out;
    ll cost;
};
struct Edge {
    Vertex *target;
    ll cost;
};

struct SegTree {
    int l,r;
    Vertex v;
    SegTree *chl, *chr;
    SegTree(int l, int r): l(l), r(r) {
        v.cost = -1;
        v.out.clear();
        v.name = "Tree Node [" + to_string(l) + "," + to_string(r) + "]";
        if (l != r) {
            int m = (l+r-1)/2;
            chl = new SegTree(l,m);
            chr = new SegTree(m+1,r);
        } else {
            chl = NULL;
            chr = NULL;
        }
    }
    ~SegTree() {
        delete chl;
        delete chr;
    }
};

const int MAXN = 100000;
Vertex planet[MAXN+1];
///

void addEdge(Vertex *a, Vertex *b, ll cost = 0) {
    Edge e;
    e.cost = cost;
    e.target = b;
    a->out.push_back(e);
    err("Built edge from (%s) to (%s)\n",a->name.c_str(),b->name.c_str());
}

void upArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(planet + t->l, &(t->v));
        return;
    }
    addEdge(&(t->chl->v),&(t->v));
    addEdge(&(t->chr->v),&(t->v));
    upArrows(t->chl);
    upArrows(t->chr);
}

void downArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(&(t->v), planet + t->l);
        return;
    }
    addEdge(&(t->v),&(t->chl->v));
    addEdge(&(t->v),&(t->chr->v));
    downArrows(t->chl);
    downArrows(t->chr);
}

void edgesToTree(Vertex *src, SegTree *t, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(src,&(t->v),cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesToTree(src,t->chl,l,r,cost);
    edgesToTree(src,t->chr,l,r,cost);
}

void edgesFromTree(SegTree *t, Vertex *tar, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(&(t->v), tar, cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesFromTree(t->chl, tar, l, r, cost);
    edgesFromTree(t->chr, tar, l, r, cost);
}

struct Offer {
    Vertex *v;
    ll candCost;
    Offer(Vertex *v, ll cc): v(v), candCost(cc) {}
};

struct offCmp {
    bool operator() (const Offer &a, const Offer &b) const {
        return a.candCost > b.candCost;
    }
};

void solve_testcase() {
    SegTree upTree(1,n);
    SegTree downTree(1,n);
    for (int i=1; i<=n; i++) {
        planet[i].cost = -1;
        planet[i].out.clear();
        planet[i].name = "Planet " + to_string(i);
    }
    upArrows(&upTree);
    downArrows(&downTree);

    for (int i=0; i<q; i++) {
        int t; cin >> t;
        if (t == 1) {
            int v,u,w; cin >> v >> u >> w;
            addEdge(planet+v, planet+u, w);
        } else {
            int v,l,r,w; cin >> v >> l >> r >> w;
            if (t == 2) { // From v to [l,r].. send to the down-tree
                edgesToTree(planet+v,&downTree,l,r,w);
            } else { // from [l,r] to v
                edgesFromTree(&upTree,planet+v,l,r,w);
            }
        }
    }

    // Djikstra
    priority_queue<Offer,vector<Offer>,offCmp> pq;
    Vertex *earth = planet+s;
    Offer init(earth,0);
    pq.push(init);
    while (!pq.empty()) {
        Offer o = pq.top();
        pq.pop();
        Vertex *v = o.v;
        err("Processing %s...\n",v->name.c_str());
        if (v->cost != -1) continue; //Already seen
        v->cost = o.candCost;
        for (int i=0; i<v->out.size(); i++) {
            Edge e = v->out[i];
            Vertex *w = e.target;
            ll cand = v->cost + e.cost;
            if (w->cost != -1) continue;
            pq.push(Offer(w,cand));
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    printf("\n");
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int n,q,s;
struct Edge;
struct Vertex {
    string name;
    vector<Edge> out;
    ll cost;
};
struct Edge {
    Vertex *target;
    ll cost;
};

struct SegTree {
    int l,r;
    Vertex v;
    SegTree *chl, *chr;
    SegTree(int l, int r): l(l), r(r) {
        v.cost = -1;
        v.out.clear();
        v.name = "Tree Node [" + to_string(l) + "," + to_string(r) + "]";
        if (l != r) {
            int m = (l+r-1)/2;
            chl = new SegTree(l,m);
            chr = new SegTree(m+1,r);
        } else {
            chl = NULL;
            chr = NULL;
        }
    }
    ~SegTree() {
        delete chl;
        delete chr;
    }
};

const int MAXN = 100000;
Vertex planet[MAXN+1];
///

void addEdge(Vertex *a, Vertex *b, ll cost = 0) {
    Edge e;
    e.cost = cost;
    e.target = b;
    a->out.push_back(e);
    err("Built edge from (%s) to (%s)\n",a->name.c_str(),b->name.c_str());
}

void upArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(planet + t->l, &(t->v));
        return;
    }
    addEdge(&(t->chl->v),&(t->v));
    addEdge(&(t->chr->v),&(t->v));
    upArrows(t->chl);
    upArrows(t->chr);
}

void downArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(&(t->v), planet + t->l);
        return;
    }
    addEdge(&(t->v),&(t->chl->v));
    addEdge(&(t->v),&(t->chr->v));
    downArrows(t->chl);
    downArrows(t->chr);
}

void edgesToTree(Vertex *src, SegTree *t, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(src,&(t->v),cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesToTree(src,t->chl,l,r,cost);
    edgesToTree(src,t->chr,l,r,cost);
}

void edgesFromTree(SegTree *t, Vertex *tar, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(&(t->v), tar, cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesFromTree(t->chl, tar, l, r, cost);
    edgesFromTree(t->chr, tar, l, r, cost);
}

struct Offer {
    Vertex *v;
    ll candCost;
    Offer(Vertex *v, ll cc): v(v), candCost(cc) {}
};

struct offCmp {
    bool operator() (const Offer &a, const Offer &b) const {
        return a.candCost > b.candCost;
    }
};

void solve_testcase() {
    SegTree upTree(1,n);
    SegTree downTree(1,n);
    for (int i=1; i<=n; i++) {
        planet[i].cost = -1;
        planet[i].out.clear();
        planet[i].name = "Planet " + to_string(i);
    }
    upArrows(&upTree);
    downArrows(&downTree);

    for (int i=0; i<q; i++) {
        int t; cin >> t;
        if (t == 1) {
            int v,u,w; cin >> v >> u >> w;
            addEdge(planet+v, planet+u, w);
        } else {
            int v,l,r,w; cin >> v >> l >> r >> w;
            if (t == 2) { // From v to [l,r].. send to the down-tree
                edgesToTree(planet+v,&downTree,l,r,w);
            } else { // from [l,r] to v
                edgesFromTree(&upTree,planet+v,l,r,w);
            }
        }
    }

    // Djikstra
    priority_queue<Offer,vector<Offer>,offCmp> pq;
    Vertex *earth = planet+s;
    Offer init(earth,0);
    pq.push(init);
    while (!pq.empty()) {
        Offer o = pq.top();
        pq.pop();
        Vertex *v = o.v;
        err("Processing %s...\n",v->name.c_str());
        if (v->cost != -1) continue; //Already seen
        v->cost = o.candCost;
        for (int i=0; i<v->out.size(); i++) {
            Edge e = v->out[i];
            Vertex *w = e.target;
            int cand = v->cost + e.cost;
            if (w->cost != -1) continue;
            pq.push(Offer(w,cand));
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    printf("\n");
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    void init() {
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): cost(cost), end(end) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[2*MAXN+2];
Vertex tarT[2*MAXN+2];
///

int parent(int i) {
    if (i == (i&-i) && 2*i > 2*n+1) return 0; // Root
    int j = i;
    do {
        int d = j&-j;
        j = (j ^ d) | (d<<1);
    } while (j > 2*n+1);
    return j;
}

void link(Vertex *a, Vertex *b, int cost) {
    a->out.push_back(Path(b,cost));
}

struct Parts {
    Vertex *root;
    int l;
    int r;
    Parts(Vertex *root, int l, int r): root(root), l(l), r(r) {}
    Vertex *next() {
        assert(l <= r);
        if (l == r) return NULL;
        Vertex *res;
        int d = l&-l;
        if (l+d <= r) {
            res = root + (2*l+d);
            l += d;
        } else {
            d = r&-r;
            r -= d;
            res = root + (2*r+d);
        }
        return res;
    }
};

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u,w; cin >> u >> w;
            link(planet+v,planet+u,w);
        } else {
            int r,l,w; cin >> l >> r >> w;
            Vertex *u;
            if (t==2) {
                Parts p(tarT,l,r+1);
                while ((u = p.next()) != NULL) link(planet+v,u,w);
            } else {
                Parts p(srcT,l,r+1);
                while ((u = p.next()) != NULL) link(u,planet+v,w);
            }
        }
    }
    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path p = pq.top(); pq.pop();
        if (p.end->cost != -1) continue;
        p.end->cost = p.cost;
        for (int i=0; i<p.end->out.size(); i++) {
            pq.push( Path(p.end->out[i].end, p.cost + p.end->out[i].cost) );
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=2*n+1; i++) {
        srcT[i].init();
        tarT[i].init();
        int j = parent(i);
        if (j) {
            link(srcT+i,srcT+j,0);
            link(tarT+j,tarT+i,0);
        }
    }
    for (int i=1; i<=n; i++) {
        planet[i].init();
        link(planet+i,srcT+2*i+1,0);
        link(tarT+2*i+1,planet+i,0);
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


// Seems over-complicated. Anyway, it doesn't work.

#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

const int MAXN = 200000;
int n,q,s;

struct Portal {
    int sl,sr;
    int tl,tr;
    ll cost; // Cost to use this portal
    ll totCost; //Total cose to get from the source to the target
    bool seen;
};
struct pscmp {
    bool operator() (const Portal *a, const Portal *b) {
        return a->totCost > b->totCost;
    }
};
priority_queue<Portal *, vector<Portal *>, pscmp> pq;
Portal portals[MAXN];

struct Node {
    int l,r;
    Node *chL, *chR;
    ll bestScore;
    vector<Portal *> covers;
    vector<Portal *> occurs;
    void init(int ll, int rr);
};
struct Node;
Node nodes[MAXN];
Node *nextNode;

void Node::init(int ll, int rr) {
    l = ll;
    r = rr;
    bestScore = -1;
    if (l == r) chL = chR = NULL;
    else {
        chL = nextNode++;
        chR = nextNode++;
        int m = (l+r+1)/2;
        chL->init(l,m-1);
        chR->init(m,r);
    }
}

void addPortal(Portal *p, Node *n) {
    if (p->tr < n->l || p->tl > n->r) return;
    //err("Portal [%d,%d]->[%d,%d] added to interval [%d,%d]...\n",p->sl,p->sr,p->tl,p->tr,n->l,n->r);
    if (p->tl <= n-> l && p->tr >= n->r) {
        n->covers.push_back(p);
    } else {
        n->occurs.push_back(p);
        addPortal(p,n->chL);
        addPortal(p,n->chR);
    }
}

void offerPortal(Portal *p, ll soFarCost) {
    if (!p->seen) {
        //err("Portal [%d,%d]->[%d,%d] (cost %d) target is %d away from Earth!\n",p->sl,p->sr,p->tl,p->tr,p->cost,soFarCost);
        p->seen = true;
        p->totCost = p->cost + soFarCost;
        pq.push(p);
    }
}

void updateMin(int l, int r, Node *n, ll totCost) {
    if (r < n->l || l > n->r) return;
    for (int i=0; i<n->covers.size(); i++) {
        offerPortal(n->covers[i],totCost);
    }
    if (l <= n->l && r >= n->r) {
        if (n->bestScore == -1 || n->bestScore > totCost) n->bestScore = totCost;
        for (int i=0; i<n->occurs.size(); i++) {
            offerPortal(n->occurs[i],totCost);
        }
    } else {
        updateMin(l,r,n->chL,totCost);
        updateMin(l,r,n->chR,totCost);
    }
}

ll getScore(int i, Node *n) {
    ll res = -1;
    while (n != NULL) {
        ll cand = n->bestScore;
        if (cand != -1) {
            if (res == -1 || res > cand) {
                res = cand;
            }
        }
        ll m = (n->l + n->r + 1)/2;
        if (i < m) n = n->chL;
        else n = n->chR;
    }
    return res;
}

void solve_testcase() {
    nextNode = nodes+1;
    nodes[0].init(1,n);
    // Initialize the portal vectors
    for (int i=0; i<q; i++) addPortal(portals+i,nodes);
    updateMin(s,s,nodes,0);
    while (!pq.empty()) {
        Portal *p = pq.top();
        pq.pop();
        updateMin(p->sl,p->sr,nodes,p->totCost);
    }
    for (int i=1; i<=n; i++) cout << getScore(i,nodes) << " ";
    printf("\n");
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=0; i<q; i++) {
        Portal *p = portals+i;
        p->seen = false;
        int t; if (scanf("%d",&t) != 1) return false;
        if (t == 1) {
            int v,u,w; if (scanf("%d %d %d",&v,&u,&w) != 3) return false;
            p->tl = v;
            p->tr = v;
            p->sl = u;
            p->sr = u;
            p->cost = w;
        } else {
            int v,l,r,w; if (scanf("%d %d %d %d",&v,&l,&r,&w) != 4) return false;
            if (t == 2) {
                p->tl = v;
                p->tr = v;
                p->sl = l;
                p->sr = r;
            } else {
                p->tl = l;
                p->tr = r;
                p->sl = v;
                p->sr = v;
            }
            p->cost = w;
        }
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int n,q,s;
struct Edge;
struct Vertex {
    string name;
    vector<Edge> out;
    int cost;
};
struct Edge {
    Vertex *target;
    int cost;
};

struct SegTree {
    int l,r;
    Vertex v;
    SegTree *chl, *chr;
    SegTree(int l, int r): l(l), r(r) {
        v.cost = -1;
        v.out.clear();
        v.name = "Tree Node [" + to_string(l) + "," + to_string(r) + "]";
        if (l != r) {
            int m = (l+r-1)/2;
            chl = new SegTree(l,m);
            chr = new SegTree(m+1,r);
        } else {
            chl = NULL;
            chr = NULL;
        }
    }
    ~SegTree() {
        delete chl;
        delete chr;
    }
};

const int MAXN = 100000;
Vertex planet[MAXN+1];
///

void addEdge(Vertex *a, Vertex *b, int cost = 0) {
    Edge e;
    e.cost = cost;
    e.target = b;
    a->out.push_back(e);
    err("Built edge from (%s) to (%s)\n",a->name.c_str(),b->name.c_str());
}

void upArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(planet + t->l, &(t->v));
        return;
    }
    addEdge(&(t->chl->v),&(t->v));
    addEdge(&(t->chr->v),&(t->v));
    upArrows(t->chl);
    upArrows(t->chr);
}

void downArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(&(t->v), planet + t->l);
        return;
    }
    addEdge(&(t->v),&(t->chl->v));
    addEdge(&(t->v),&(t->chr->v));
    downArrows(t->chl);
    downArrows(t->chr);
}

void edgesToTree(Vertex *src, SegTree *t, int l, int r, int cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(src,&(t->v),cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesToTree(src,t->chl,l,r,cost);
    edgesToTree(src,t->chr,l,r,cost);
}

void edgesFromTree(SegTree *t, Vertex *tar, int l, int r, int cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(&(t->v), tar, cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesFromTree(t->chl, tar, l, r, cost);
    edgesFromTree(t->chr, tar, l, r, cost);
}

struct Offer {
    Vertex *v;
    int candCost;
    Offer(Vertex *v, int cc): v(v), candCost(cc) {}
};

struct offCmp {
    bool operator() (const Offer &a, const Offer &b) const {
        return a.candCost > b.candCost;
    }
};

void solve_testcase() {
    SegTree upTree(1,n);
    SegTree downTree(1,n);
    for (int i=1; i<=n; i++) {
        planet[i].cost = -1;
        planet[i].out.clear();
        planet[i].name = "Planet " + to_string(i);
    }
    upArrows(&upTree);
    downArrows(&downTree);

    for (int i=0; i<q; i++) {
        int t; cin >> t;
        if (t == 1) {
            int v,u,w; cin >> v >> u >> w;
            addEdge(planet+v, planet+u, w);
        } else {
            int v,l,r,w; cin >> v >> l >> r >> w;
            if (t == 2) { // From v to [l,r].. send to the down-tree
                edgesToTree(planet+v,&downTree,l,r,w);
            } else { // from [l,r] to v
                edgesFromTree(&upTree,planet+v,l,r,w);
            }
        }
    }

    // Djikstra
    priority_queue<Offer,vector<Offer>,offCmp> pq;
    Vertex *earth = planet+s;
    Offer init(earth,0);
    pq.push(init);
    while (!pq.empty()) {
        Offer o = pq.top();
        pq.pop();
        Vertex *v = o.v;
        err("Processing %s...\n",v->name.c_str());
        if (v->cost != -1) continue; //Already seen
        v->cost = o.candCost;
        for (int i=0; i<v->out.size(); i++) {
            Edge e = v->out[i];
            Vertex *w = e.target;
            int cand = v->cost + e.cost;
            if (w->cost != -1) continue;
            pq.push(Offer(w,cand));
        }
    }
    for (int i=1; i<=n; i++) printf("%d ",planet[i].cost);
    printf("\n");
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    //string name;
    void init() {
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): cost(cost), end(end) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[2*MAXN+2];
Vertex tarT[2*MAXN+2];
///

int parent(int i) {
    if (i == (i&-i) && 2*i > 2*n+1) return 0; // Root
    int j = i;
    do {
        int d = j&-j;
        j = (j ^ d) | (d<<1);
    } while (j > 2*n+1);
    return j;
}

void link(Vertex *a, Vertex *b, int cost) {
    //err("Edge: (%s) -> (%s) cost %d\n",a->name.c_str(),b->name.c_str(),cost);
    a->out.push_back(Path(b,cost));
}

struct Parts {
    Vertex *root;
    int l;
    int r;
    Parts(Vertex *root, int l, int r): root(root), l(l), r(r) {}
    Vertex *next() {
        assert(l <= r);
        if (l == r) return NULL;
        int index;
        int d = l&-l;
        if (l+d <= r) {
            index = (2*l+d);
            l = min(l+d,n+1);
        } else {
            do {d >>= 1;} while (!(d&r));
            index = (2*l+d);
            l += d;
        }
        while (index > 2*n+1) index = parent(index);
        //err("[%d,%d)...",(index - (index&-index))/2,(index+(index&-index))/2);
        return root + index;
    }
};

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u,w; cin >> u >> w;
            link(planet+v,planet+u,w);
        } else {
            int r,l,w; cin >> l >> r >> w;
            Vertex *u;
            //err("breaking up [%d,%d): ",l,r+1);
            if (t==2) {
                Parts p(tarT,l,r+1);
                while ((u = p.next()) != NULL) link(planet+v,u,w);
                //err("\n");
            } else {
                Parts p(srcT,l,r+1);
                while ((u = p.next()) != NULL) link(u,planet+v,w);
                //err("\n");
            }
        }
    }
    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path p = pq.top(); pq.pop();
        if (p.end->cost != -1) continue;
        //err("Let's visit (%s)\n",p.end->name.c_str());
        p.end->cost = p.cost;
        for (int i=0; i<p.end->out.size(); i++) {
            pq.push( Path(p.end->out[i].end, p.cost + p.end->out[i].cost) );
            //err("--found a route to (%s)\n",p.end->out[i].end->name.c_str());
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    if (!cin.good()) return false;
    /*for (int i=1; i<=2*n+1; i++) {
        string suff = "[" + to_string((i-(i&-i))/2) + "," + to_string(min(n,(i+(i&-i))/2-1)) + "]";
        srcT[i].name = "SRC-" + suff;
        tarT[i].name = "TAR-" + suff;
    }*/
    for (int i=1; i<=2*n+1; i++) {
        srcT[i].init();
        tarT[i].init();
    }
    for (int i=1; i<=2*n+1; i++) {
        int j = parent(i);
        if (j) {
            link(srcT+i,srcT+j,0);
            link(tarT+j,tarT+i,0);
            //err("Parent of [%d,%d] is [%d,%d]\n",(i-(i&-i))/2,(i+(i&-i))/2-1,(j-(j&-j))/2,(j+(j&-j))/2-1);
        }
    }
    for (int i=1; i<=n; i++) {
        planet[i].init();
        //planet[i].name = "PLANET-" + to_string(i);
        link(planet+i,srcT+(2*i+1),0);
        link(tarT+(2*i+1),planet+i,0);
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


// Trying again, different syntax... currently get a runtime error... array index out of bounds?

#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int tot = 0;

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    int id;
    void init() {
        id = ++tot;
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): end(end), cost(cost) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[4*MAXN];
Vertex tarT[4*MAXN];
///

void expand(vector<Vertex *> &res, int l, int r, Vertex *root, int i, int tl, int tr) {
    if (r < tl || l > tr) return;
    if (l <= tl && r >= tr) res.push_back(root+i);
    else {
        int tm = (tl+tr)/2;
        expand(res,l,r,root,2*i+1,tl,tm);
        expand(res,l,r,root,2*i+2,tm+1,tr);
    }
}

void adjoin(int sl, int sr, int tl, int tr, int cost) {
    vector<Vertex *> sv,tv;
    expand(sv,sl,sr,srcT,0,1,n);
    expand(tv,tl,tr,tarT,0,1,n);
    for (int i=0; i<sv.size(); i++) for (int j=0; j<tv.size(); j++) {
        //err("Edge %d->%d (cost %d)\n",sv[i]->id,tv[j]->id,cost);
        sv[i]->out.push_back( Path(tv[j],cost) );
    }
}

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u; ll w; cin >> u >> w;
            adjoin(v,v,u,u,w);
        } else {
            int l,r; ll w; cin >> l >> r >> w;
            if (t==2) adjoin(v,v,l,r,w);
            else adjoin(l,r,v,v,w);
        }
    }

    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path cu = pq.top(); pq.pop();
        if (cu.end->cost != -1) continue;
        cu.end->cost = cu.cost;
        for (int i=0; i<cu.end->out.size(); i++) {
            Path nx(cu.end->out[i].end, cu.cost + cu.end->out[i].cost);
            pq.push(nx);
        }
    }
    for (int i=1; i<=n; i++) {
        cout << planet[i].cost << " ";
    }
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=n; i++) planet[i].init();
    for (int i=0; i<4*n; i++) {
        srcT[i].init();
        tarT[i].init();
        if (i != 0) {
            int j = (i-1)/2;
            srcT[i].out.push_back( Path(srcT+j,0) );
            tarT[j].out.push_back( Path(tarT+i,0) );
        }
    }
    for (int i=1; i<=n; i++) {
        vector<Vertex *> ss,tt;
        expand(ss,i,i,srcT,0,1,n); expand(tt,i,i,tarT,0,1,n);
        planet[i].out.push_back( Path( ss[0], 0));
        tt[0]->out.push_back(Path(planet+i,0));
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    void init() {
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): cost(cost), end(end) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 100000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[2*MAXN+2];
Vertex tarT[2*MAXN+2];
///

int parent(int i) {
    if (i == (i&-i) && 2*i > 2*n+1) return 0; // Root
    int j = i;
    do {
        int d = j&-j;
        j = (j ^ d) | (d<<1);
    } while (j > 2*n+1);
    return j;
}

void link(Vertex *a, Vertex *b, int cost) {
    a->out.push_back(Path(b,cost));
}

struct Parts {
    Vertex *root;
    int l;
    int r;
    Parts(Vertex *root, int l, int r): root(root), l(l), r(r) {}
    Vertex *next() {
        assert(l <= r);
        if (l == r) return NULL;
        int index;
        int d = l&-l;
        if (min(l+d,2*n+1) <= r) {
            index = (2*l+d);
            l = min(l+d,2*n+1);
        } else {
            d = r&-r;
            r -= d;
            index = (2*r+d);
        }
        while (index > 2*n+1) index = parent(index);
        return root + index;
    }
};

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u,w; cin >> u >> w;
            link(planet+v,planet+u,w);
        } else {
            int r,l,w; cin >> l >> r >> w;
            Vertex *u;
            if (t==2) {
                Parts p(tarT,l,r+1);
                while ((u = p.next()) != NULL) link(planet+v,u,w);
            } else {
                Parts p(srcT,l,r+1);
                while ((u = p.next()) != NULL) link(u,planet+v,w);
            }
        }
    }
    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path p = pq.top(); pq.pop();
        if (p.end->cost != -1) continue;
        p.end->cost = p.cost;
        for (int i=0; i<p.end->out.size(); i++) {
            pq.push( Path(p.end->out[i].end, p.cost + p.end->out[i].cost) );
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=2*n+1; i++) {
        srcT[i].init();
        tarT[i].init();
        int j = parent(i);
        if (j) {
            link(srcT+i,srcT+j,0);
            link(tarT+j,tarT+i,0);
        }
    }
    for (int i=1; i<=n; i++) {
        planet[i].init();
        link(planet+i,srcT+2*i+1,0);
        link(tarT+2*i+1,planet+i,0);
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


// Trying again, different syntax... currently get a runtime error... array index out of bounds?

#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int tot = 0;

struct Path;
struct Vertex {
    vector<Path> out;
    ll cost;
    int id;
    void init() {
        id = ++tot;
        out.clear();
        cost = -1;
    }
};
struct Path {
    Vertex *end;
    ll cost;
    Path(Vertex *end, ll cost): end(end), cost(cost) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};

const int MAXN = 10000;
/// Testcase variables
int n,q,s;
Vertex planet[MAXN+1];
Vertex srcT[4*MAXN];
Vertex tarT[4*MAXN];
///

void expand(vector<Vertex *> &res, int l, int r, Vertex *root, int i, int tl, int tr) {
    if (r < tl || l > tr) return;
    if (l <= tl && r >= tr) res.push_back(root+i);
    else {
        int tm = (tl+tr)/2;
        expand(res,l,r,root,2*i+1,tl,tm);
        expand(res,l,r,root,2*i+2,tm+1,tr);
    }
}

void adjoin(int sl, int sr, int tl, int tr, int cost) {
    vector<Vertex *> sv,tv;
    expand(sv,sl,sr,srcT,0,1,n);
    expand(tv,tl,tr,tarT,0,1,n);
    for (int i=0; i<sv.size(); i++) for (int j=0; j<tv.size(); j++) {
        //err("Edge %d->%d (cost %d)\n",sv[i]->id,tv[j]->id,cost);
        sv[i]->out.push_back( Path(tv[j],cost) );
    }
}

void solve_testcase() {
    for (int i=0; i<q; i++) {
        int t,v; cin >> t >> v;
        if (t==1) {
            int u; ll w; cin >> u >> w;
            adjoin(v,v,u,u,w);
        } else {
            int l,r; ll w; cin >> l >> r >> w;
            if (t==2) adjoin(v,v,l,r,w);
            else adjoin(l,r,v,v,w);
        }
    }

    priority_queue<Path> pq;
    pq.push( Path(planet+s,0) );
    while (!pq.empty()) {
        Path cu = pq.top(); pq.pop();
        if (cu.end->cost != -1) continue;
        cu.end->cost = cu.cost;
        for (int i=0; i<cu.end->out.size(); i++) {
            Path nx(cu.end->out[i].end, cu.cost + cu.end->out[i].cost);
            pq.push(nx);
        }
    }
    for (int i=1; i<=n; i++) {
        cout << planet[i].cost << " ";
    }
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    for (int i=1; i<=n; i++) planet[i].init();
    for (int i=0; i<4*n; i++) {
        srcT[i].init();
        tarT[i].init();
        if (i != 0) {
            int j = (i-1)/2;
            srcT[i].out.push_back( Path(srcT+j,0) );
            tarT[j].out.push_back( Path(tarT+i,0) );
        }
    }
    for (int i=1; i<=n; i++) {
        vector<Vertex *> ss,tt;
        expand(ss,i,i,srcT,0,1,n); expand(tt,i,i,tarT,0,1,n);
        planet[i].out.push_back( Path( ss[0], 0));
        tt[0]->out.push_back(Path(planet+i,0));
    }
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

/// Testcase variables
const int MAXN = 100001;
int n,q,s;

struct Node;
struct Path {
    Node *tar;
    ll cost;
    Path(Node *tar, ll cost): tar(tar), cost(cost) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};
struct Node {
    ll cost;
    vector<Path> out;
    void init() {
        cost = -1;
        out.clear();
    }
};

Node planet[MAXN];
Node tarTree[2*MAXN];
Node srcTree[2*MAXN];
int l[2*MAXN], r[2*MAXN];
///

void addPath(int sl, int sr, int tl, int tr, int cost, int si = 0, int ti = 0) {
    if (sl > r[si] || sr < l[si] || tl > r[ti] || tr < l[ti]) return;
    if (sl > l[si] || sr < r[si]) {
        addPath(sl,sr,tl,tr,cost,2*si+1,ti);
        addPath(sl,sr,tl,tr,cost,2*si+2,ti);
    } else if  (tl > l[ti] || tr < r[ti]) {
        addPath(sl,sr,tl,tr,cost,si,2*ti+1);
        addPath(sl,sr,tl,tr,cost,si,2*ti+2);
    } else {
        srcTree[si].out.push_back( Path(tarTree+ti, cost) );
    }
}

void solve_testcase() {
    for (int i=1; i<=n; i++) planet[i].init();
    l[0] = 1; r[0] = n; tarTree[0].init(); srcTree[0].init();
    for (int i=1 ;; i++) {
        int j=(i-1)/2; if (l[j] == r[j]) break;
        tarTree[i].init(); srcTree[i].init();
        int mid = (l[j] + r[j])/2;
        l[i] = (i%2)? mid+1 : l[j];
        r[i] = (i%2)? r[j] : mid;
        srcTree[i].out.push_back(Path(srcTree+j,0));
        tarTree[j].out.push_back(Path(tarTree+i,0));
        if (l[i] == r[i]) {
            planet[l[i]].out.push_back(Path(srcTree+i,0));
            tarTree[l[i]].out.push_back(Path(planet+l[i],0));
        }
    }

    for (int i=0; i<q; i++) {
        int t,v,u,l,r,w;
        cin >> t >> v;
        if (t==1) {
            cin >> u >> w;
            addPath(v,v,u,u,w);
        } else if (t==2) {
            cin >> l >> r >> w;
            addPath(v,v,l,r,w);
        } else {
            cin >> l >> r >> w;
            addPath(l,r,v,v,w);
        }
    }

    //Djikstra
    priority_queue<Path> pq;
    Path init(planet+s,0);
    while (!pq.empty()) {
        Path p = pq.top();
        pq.pop(); Node *v = p.tar;
        if (v->cost != -1) continue;
        v->cost = p.cost;
        for (int i=0; i<v->out.size(); i++) {
            Path q = v->out[i];
            if (q.tar->cost != -1) continue;
            pq.push( Path(q.tar, v->cost + q.cost) );
        }
    }

    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
    // Read the portals in solve_testcase instead.
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

/// Testcase variables
const int MAXN = 100001;
int n,q,s;

struct Node;
struct Path {
    Node *tar;
    ll cost;
    Path(Node *tar, ll cost): tar(tar), cost(cost) {}
    bool operator< (const Path &other) const {
        return cost > other.cost;
    }
};
struct Node {
    ll cost;
    vector<Path> out;
    void init() {
        cost = -1;
        out.clear();
    }
};

Node planet[MAXN];
Node tarTree[2*MAXN];
Node srcTree[2*MAXN];
int l[2*MAXN], r[2*MAXN];
///

void addPath(int sl, int sr, int tl, int tr, int cost, int si = 0, int ti = 0) {
    if (sl > r[si] || sr < l[si] || tl > r[ti] || tr < l[ti]) return;
    if (sl > l[si] || sr < r[si]) {
        addPath(sl,sr,tl,tr,cost,2*si+1,ti);
        addPath(sl,sr,tl,tr,cost,2*si+2,ti);
    } else if  (tl > l[ti] || tr < r[ti]) {
        addPath(sl,sr,tl,tr,cost,si,2*ti+1);
        addPath(sl,sr,tl,tr,cost,si,2*ti+2);
    } else {
        srcTree[si].out.push_back( Path(tarTree+ti, cost) );
    }
}

void solve_testcase() {
    for (int i=1; i<=n; i++) planet[i].init();
    l[0] = 1; r[0] = n; tarTree[0].init(); srcTree[0].init();
    for (int i=1 ;; i++) {
        int j=(i-1)/2; if (l[j] == r[j]) break;
        tarTree[i].init(); srcTree[i].init();
        int mid = (l[j] + r[j])/2;
        l[i] = (i%2)? l[j] : mid+1;
        r[i] = (i%2)? mid : r[j];
        srcTree[i].out.push_back(Path(srcTree+j,0));
        tarTree[j].out.push_back(Path(tarTree+i,0));
        if (l[i] == r[i]) {
            planet[l[i]].out.push_back(Path(srcTree+i,0));
            tarTree[i].out.push_back(Path(planet+l[i],0));
        }
    }

    for (int i=0; i<q; i++) {
        int t,v,u,l,r,w;
        cin >> t >> v;
        if (t==1) {
            cin >> u >> w;
            addPath(v,v,u,u,w);
        } else if (t==2) {
            cin >> l >> r >> w;
            addPath(v,v,l,r,w);
        } else {
            cin >> l >> r >> w;
            addPath(l,r,v,v,w);
        }
    }

    //Djikstra
    priority_queue<Path> pq;
    pq.push( Path(planet+s, 0) );
    while (!pq.empty()) {
        Path p = pq.top();
        pq.pop(); Node *v = p.tar;
        if (v->cost != -1) continue;
        v->cost = p.cost;
        for (int i=0; i<v->out.size(); i++) {
            Path q = v->out[i];
            if (q.tar->cost != -1) continue;
            pq.push( Path(q.tar, v->cost + q.cost) );
        }
    }

    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    cout << endl;
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
    // Read the portals in solve_testcase instead.
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include <cassert>
#include <ctime>
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>

using namespace std;
typedef long long ll;
#define err(...) fprintf(stderr,__VA_ARGS__)

int n,q,s;
struct Edge;
struct Vertex {
    //string name;
    vector<Edge> out;
    ll cost;
};
struct Edge {
    Vertex *target;
    ll cost;
};

struct SegTree {
    int l,r;
    Vertex v;
    SegTree *chl, *chr;
    SegTree(int l, int r): l(l), r(r) {
        v.cost = -1;
        v.out.clear();
        //v.name = "Tree Node [" + to_string(l) + "," + to_string(r) + "]";
        if (l != r) {
            int m = (l+r-1)/2;
            chl = new SegTree(l,m);
            chr = new SegTree(m+1,r);
        } else {
            chl = NULL;
            chr = NULL;
        }
    }
    ~SegTree() {
        delete chl;
        delete chr;
    }
};

const int MAXN = 100000;
Vertex planet[MAXN+1];
///

void addEdge(Vertex *a, Vertex *b, ll cost = 0) {
    Edge e;
    e.cost = cost;
    e.target = b;
    a->out.push_back(e);
    //err("Built edge from (%s) to (%s)\n",a->name.c_str(),b->name.c_str());
}

void upArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(planet + t->l, &(t->v));
        return;
    }
    addEdge(&(t->chl->v),&(t->v));
    addEdge(&(t->chr->v),&(t->v));
    upArrows(t->chl);
    upArrows(t->chr);
}

void downArrows(SegTree *t) {
    if (t->chl == NULL) {
        addEdge(&(t->v), planet + t->l);
        return;
    }
    addEdge(&(t->v),&(t->chl->v));
    addEdge(&(t->v),&(t->chr->v));
    downArrows(t->chl);
    downArrows(t->chr);
}

void edgesToTree(Vertex *src, SegTree *t, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(src,&(t->v),cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesToTree(src,t->chl,l,r,cost);
    edgesToTree(src,t->chr,l,r,cost);
}

void edgesFromTree(SegTree *t, Vertex *tar, int l, int r, ll cost) {
    if (r < t->l || l > t->r) return;
    if (l <= t->l && r >= t->r) {
        addEdge(&(t->v), tar, cost);
        return;
    }
    assert(t->chl && t->chr);
    edgesFromTree(t->chl, tar, l, r, cost);
    edgesFromTree(t->chr, tar, l, r, cost);
}

struct Offer {
    Vertex *v;
    ll candCost;
    Offer(Vertex *v, ll cc): v(v), candCost(cc) {}
};

struct offCmp {
    bool operator() (const Offer &a, const Offer &b) const {
        return a.candCost > b.candCost;
    }
};

void solve_testcase() {
    SegTree upTree(1,n);
    SegTree downTree(1,n);
    for (int i=1; i<=n; i++) {
        planet[i].cost = -1;
        planet[i].out.clear();
        //planet[i].name = "Planet " + to_string(i);
    }
    upArrows(&upTree);
    downArrows(&downTree);

    for (int i=0; i<q; i++) {
        int t; cin >> t;
        if (t == 1) {
            int v,u,w; cin >> v >> u >> w;
            addEdge(planet+v, planet+u, w);
        } else {
            int v,l,r,w; cin >> v >> l >> r >> w;
            if (t == 2) { // From v to [l,r].. send to the down-tree
                edgesToTree(planet+v,&downTree,l,r,w);
            } else { // from [l,r] to v
                edgesFromTree(&upTree,planet+v,l,r,w);
            }
        }
    }

    // Djikstra
    priority_queue<Offer,vector<Offer>,offCmp> pq;
    Vertex *earth = planet+s;
    Offer init(earth,0);
    pq.push(init);
    while (!pq.empty()) {
        Offer o = pq.top();
        pq.pop();
        Vertex *v = o.v;
        //err("Processing %s...\n",v->name.c_str());
        if (v->cost != -1) continue; //Already seen
        v->cost = o.candCost;
        for (int i=0; i<v->out.size(); i++) {
            Edge e = v->out[i];
            Vertex *w = e.target;
            ll cand = v->cost + e.cost;
            if (w->cost != -1) continue;
            pq.push(Offer(w,cand));
        }
    }
    for (int i=1; i<=n; i++) cout << planet[i].cost << " ";
    printf("\n");
}

bool read_testcase() {
    cin >> n >> q >> s;
    return cin.good();
}

int main(int argc, char **argv) {
    if (argc>1 && argv[1][0]!= 'x') freopen(argv[1],"r",stdin);
    if (argc>2) freopen(argv[2],"w",stdout);
    int T=1;
    clock_t cur,prev = clock();
    while (read_testcase()) {
        err(">>>Solving testcase %d<<<<\n",T);
        solve_testcase();
        cur = clock();
        int dur = (cur-prev)*1000/CLOCKS_PER_SEC;
        err("____Case %d done in %dms.\n",T,dur);
        prev = cur; T++;
    }
}


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,LL>
#define ff first
#define ss second
#define mp make_pair
#define pb push_back
#define pp pop_back
#define reg register
#define du double
#define qr read()
inline int read()
{
    char ch=' ';
    int f=1,x=0;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return f*x;
}

#define N 2333333
int n,q,s,ju;
int c[N],to[N],nxt[N];
LL len[N];
int cnt,tot;
LL dis[N];
int vis[N];
int rt1,rt2,Ls[N],Rs[N];

inline void add(int u,int v,LL l)
{
	cnt++;
	to[cnt] = v;
	len[cnt] = l;
	nxt[cnt] = c[u];
	c[u] = cnt;
}

void build1(int &p,int l,int r)
{
	if(l == r)
	{
		p = l;
		return;
	}
	p = ++tot;
	int mid = l + r >> 1;
	build1(Ls[p],l,mid);
	build1(Rs[p],mid + 1,r);
	add(p,Ls[p],0);
	add(p,Rs[p],0);
}

void build2(int &p,int l,int r)

{
	if(l == r)
	{
		p = r;
		return;
	}
	p = ++tot;
	int mid = l + r >> 1;
	build2(Ls[p],l,mid);
	build2(Rs[p],mid + 1,r);
	add(Ls[p],p,0);
	add(Rs[p],p,0);
}

void update(int &p,int l,int r,int now,int u,int v,int t)
{
	if(u <= l && r <= v)
	{
		if(ju == 2)
		{
			add(now,p,t);
		}
		if(ju == 3)
		{
			add(p,now,t);
		}
		return;
	}
	int mid = l + r >> 1;
	if(u <= mid)update(Ls[p],l,mid,now,u,v,t);
	if(v > mid)update(Rs[p],mid + 1,r,now,u,v,t);
}

void dij()
{
	for(int i = 0; i <= N - 10000; i++)dis[i] = 1e18;
	dis[s] = 0;
	priority_queue<pa,vector<pa>,greater<pa> >q;
	q.push(mp(0,s));
	while(!q.empty())
	{
		pa t = q.top();
		q.pop();
		int now = t.ss;
		LL ll = t.ff;
		if(vis[now])continue;
		vis[now] = 1;
		for(int i = c[now];i;i = nxt[i])
		{
			int v = to[i];
			if(dis[v] > ll + len[i])
			{
				dis[v] = ll + len[i];
				q.push(mp(dis[v],v));
			}
		}
	}
}

int main()
{
	n = qr;
	q = qr;
	s = qr;
	tot = n;
	build1(rt1,1,n);
	build2(rt2,1,n);
	for(int i = 1; i <= q; i++)
	{
		ju = qr;
		if(ju == 1)
		{
			int u = qr,v = qr,w = qr;
			add(u,v,w);
		}
		else
		{
			int u = qr,l = qr,r = qr,v = qr;
			if(ju == 2)
			{
				update(rt1,1,n,u,l,r,v);
			}
			if(ju == 3)
			{
				update(rt2,1,n,u,l,r,v);
			}
		}
	}
	dij();
	for(int i = 1; i <= n; i++)
	{
		if(dis[i] == 1e18)printf("-1 ");
		else printf("%lld ",dis[i]);
	}
}


#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,LL>
#define ff first
#define ss second
#define mp make_pair
#define pb push_back
#define pp pop_back
#define reg register
#define du double
#define qr read()
#define int LL
inline int read()
{
    char ch=' ';
    int f=1,x=0;
    while(!isdigit(ch)){ch=getchar();if(ch=='-')f*=-1;}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return f*x;
}

#define N 2333333
int n,q,s,ju;
int c[N],to[N],nxt[N];
LL len[N];
int cnt,tot;
LL dis[N];
int vis[N];
int rt1,rt2,Ls[N],Rs[N];

inline void add(int u,int v,LL l)
{
	cnt++;
	to[cnt] = v;
	len[cnt] = l;
	nxt[cnt] = c[u];
	c[u] = cnt;
}

void build1(int &p,int l,int r)
{
	if(l == r)
	{
		p = l;
		return;
	}
	p = ++tot;
	int mid = l + r >> 1;
	build1(Ls[p],l,mid);
	build1(Rs[p],mid + 1,r);
	add(p,Ls[p],0);
	add(p,Rs[p],0);
}

void build2(int &p,int l,int r)

{
	if(l == r)
	{
		p = r;
		return;
	}
	p = ++tot;
	int mid = l + r >> 1;
	build2(Ls[p],l,mid);
	build2(Rs[p],mid + 1,r);
	add(Ls[p],p,0);
	add(Rs[p],p,0);
}

void update(int &p,int l,int r,int now,int u,int v,LL t)
{
	if(u <= l && r <= v)
	{
		if(ju == 2)
		{
			add(now,p,t);
		}
		if(ju == 3)
		{
			add(p,now,t);
		}
		return;
	}
	int mid = l + r >> 1;
	if(u <= mid)update(Ls[p],l,mid,now,u,v,t);
	if(v > mid)update(Rs[p],mid + 1,r,now,u,v,t);
}

void dij()
{
	for(int i = 0; i <= N - 10000; i++)dis[i] = 1e18;
	dis[s] = 0;
	priority_queue<pa,vector<pa>,greater<pa> >q;
	q.push(mp(0,s));
	while(!q.empty())
	{
		pa t = q.top();
		q.pop();
		int now = t.ss;
		LL ll = t.ff;
		if(vis[now])continue;
		vis[now] = 1;
		for(int i = c[now];i;i = nxt[i])
		{
			int v = to[i];
			if(dis[v] > ll + len[i])
			{
				dis[v] = ll + len[i];
				q.push(mp(dis[v],v));
			}
		}
	}
}

signed main()
{
	n = qr;
	q = qr;
	s = qr;
	tot = n;
	build1(rt1,1,n);
	build2(rt2,1,n);
	for(int i = 1; i <= q; i++)
	{
		ju = qr;
		if(ju == 1)
		{
			int u = qr,v = qr,w = qr;
			add(u,v,w);
		}
		else
		{
			int u = qr,l = qr,r = qr;
			LL v;
			cin >> v;
			if(ju == 2)
			{
				update(rt1,1,n,u,l,r,v);
			}
			if(ju == 3)
			{
				update(rt2,1,n,u,l,r,v);
			}
		}
	}
	dij();
	for(int i = 1; i <= n; i++)
	{
		if(dis[i] == 1e18)printf("-1 ");
		else printf("%lld ",dis[i]);
	}
}