/*SPFA算法有两个优化算法 SLF 和 LLL:
SLF:Small Label First 策略,设要加入的节点是j,队首元素为i,若dist(j) < dist(i),则将j插入队首,否则插入队尾。
LLL:Large Label Last 策略,设队首元素为i,每次弹出时进行判断,队列中所有dist值的平均值为x,若dist(i)>x则将i插入到队尾,查找下一元素,直到找到某一i使得dist(i)<=x,则将i出对进行松弛操作。
*/
//小的dis在前
#include<bits/stdc++.h>
using namespace std;
int n,m,s;//起点终点开头
int u[200005],v[200005],w[200005];
int first[200005],nextt[200005];
int dis[200005];
int k2=0;
void make_edge(int a,int b,int c)
{
k2++;
u[k2]=a;
v[k2]=b;
w[k2]=c;
nextt[k2]=first[a];
first[a]=k2;
}
void clean()
{
int flag=max(n,m);
for(int i=1;i<=flag;i++)
{
first[i]=-1;
nextt[i]=-1;
}
for(int i=1;i<=n;i++)
{
if(i==s) dis[i]=0;
else dis[i]=1e9;
}
}
deque<int> q;
int book[200005];
int main()
{
cin>>n>>m>>s;
clean();
for(int i=1;i<=m;i++)
{
int a,b,c;
cin>>a>>b>>c;
make_edge(a,b,c);
}
q.push_back(s);
book[s]=1;
while(!q.empty())
{
int now_node=q.front();
q.pop_front();
book[now_node]=0;
int k=first[now_node];
while(k!=-1)
{
if(dis[v[k]]>dis[u[k]]+w[k])
{
dis[v[k]]=dis[u[k]]+w[k];
if(book[v[k]]==0)
{
book[v[k]]=1;
if(!q.empty()/*记得判空*/&&dis[v[k]]<dis[q.front()])
{
q.push_front(v[k]);
}
else q.push_back(v[k]);
}
}
k=nextt[k];
}
}
for(int i=1;i<=n;i++)
{
if(i==1) cout<<dis[i];
else cout<<" "<<dis[i];
}
cout<<endl;
return 0;
}