v#include<cstdio>
#include<queue>
using namespace std;int l[100001],tot,dis[100001],s,n,m;
inline int read()//输入优化
{
    int d=1,f=0;char c;
    while(c=getchar(),c<48||c>57)if(c=='-')d=-1;f=(f<<3)+(f<<1)+c-48;
    while(c=getchar(),c>47&&c<58) f=(f<<3)+(f<<1)+c-48;
    return d*f;
}
struct node{int next,to,w;}e[500001];//
struct heap{int u,d;};//
inline bool operator <(heap x,heap y){return x.d>y.d;}//小的在前面
inline void add(register int u,register int v,register int w){e[++tot]=(node){l[u],v,w};l[u]=tot;}//建边
bool vis[100001];//判断会不会重新走过。。。
inline void Dijstra_heap()
{
    for(register int i=0;i<=n;i++) dis[i]=2147483647;
    dis[s]=0;
    priority_queue<heap>q;
    q.push((heap){s,0});vis[s]=true;
    while(q.size())
    {
        heap u=q.top();q.pop();//取出堆顶
        int x=u.u,d=u.d;vis[x]=true;//标记
        for(register int i=l[x];i;i=e[i].next)//用其进行拓展
        {
            int y=e[i].to,w=e[i].w;
            if(dis[x]+w<dis[y])
            {
                dis[y]=dis[x]+w;//转移
                if(!vis[y]) q.push((heap){y,dis[y]}),vis[y]=true;//没有标记过则标记并放入
            }
        }
        vis[x]=false;//记得取消标记(没有也可以)
    }
    return;
}
signed main()
{
    n=read();m=read();s=read();
    for(register int i=1,x,y,z;i<=m;i++) x=read(),y=read(),z=read(),add(x,y,z);//输入
    Dijstra_heap();//dij
    for(register int i=1;i<=n;i++) printf("%d ",dis[i]);//输出
}
02-14 04:40