// Slower C++ solution:
#include <bits/stdc++.h>

#define ll long long

#define INF 1000000005

#define MOD 1000000007

#define EPS 1e-10

#define rep(i,n) for(int i=0;i<(int)(n);++i)

#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)

#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)

#define each(a,b) for(auto (a): (b))

#define all(v) (v).begin(),(v).end()

#define len(v) (int)(v).size()

#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())

#define cmx(x,y) x=max(x,y)

#define cmn(x,y) x=min(x,y)

#define fi first

#define se second

#define pb push_back

#define show(x) cout<<#x<<" = "<<(x)<<endl

#define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl

#define svec(v) cout<<#v<<":";rep(kbrni,v.size())cout<<" "<<v[kbrni];cout<<endl

#define sset(s) cout<<#s<<":";each(kbrni,s)cout<<" "<<kbrni;cout<<endl

#define smap(m) cout<<#m<<":";each(kbrni,m)cout<<" {"<<kbrni.first<<":"<<kbrni.second<<"}";cout<<endl



using namespace std;



typedef pair<int,int> P;

typedef pair<ll,ll> pll;

typedef vector<int> vi;

typedef vector<vi> vvi;

typedef vector<ll> vl;

typedef vector<double> vd;

typedef vector<P> vp;

typedef vector<string> vs;



const int MAX_N = 100005;



template<typename T> class Heap {

public:

    struct node {

        node* l; node* r; T val;

        node(T t) : l(nullptr), r(nullptr), val(t){}

    };

    node* root;

    Heap() : root(nullptr){}

    node* meld(node* a, node* b){

        if(!a) return b; if(!b) return a;

        if(a->val > b->val) swap(a, b);

        a->r = meld(a->r,b); swap(a->l, a->r);

        return a;

    }

    void push(T val){ node* p = new node(val); root = meld(root, p); }

    T top(){ return root->val; }

    void pop(){ node* p = root; root = meld(root->r, root->l); delete p; }

};





struct edge{

    int to, cost;

};



int d[MAX_N];

vector<edge> G[MAX_N];



void dijkstra(int s)

{

    Heap<P> que;

    d[s] = 0;

    que.push(P(0,s));

    while(que.root){

        P p = que.top();

        que.pop();

        int v = p.second;

        if(d[v] < p.first) continue;

        for(auto w : G[v]){

            if(d[w.to] > d[v] + w.cost){

                d[w.to] = d[v] + w.cost;

                que.push(P(d[w.to],w.to));

            }

        }

    }

}



int main()

{

    int n,m,s;

    scanf("%d%d%d",&n,&m,&s);

    rep(i,m){

        int a,b,c;

        scanf("%d%d%d",&a,&b,&c);

        G[a].pb((edge){b,c});

    }

    fill(d,d+n,INF);

    dijkstra(s);

    rep(i,n){

        if(d[i] == INF){

            cout << "INF\n";

        }else{

            cout << d[i] << "\n";

        }

    }

    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.4359959484391025x):
#include <bits/stdc++.h>

#define ll long long

#define INF 1000000005

#define MOD 1000000007

#define EPS 1e-10

#define rep(i,n) for(int i=0;i<(int)(n);++i)

#define rrep(i,n) for(int i=(int)(n)-1;i>=0;--i)

#define srep(i,s,t) for(int i=(int)(s);i<(int)(t);++i)

#define each(a,b) for(auto& (a): (b))

#define all(v) (v).begin(),(v).end()

#define len(v) (int)(v).size()

#define zip(v) sort(all(v)),v.erase(unique(all(v)),v.end())

#define cmx(x,y) x=max(x,y)

#define cmn(x,y) x=min(x,y)

#define fi first

#define se second

#define pb push_back

#define show(x) cout<<#x<<" = "<<(x)<<endl

#define spair(p) cout<<#p<<": "<<p.fi<<" "<<p.se<<endl

#define sar(a,n) cout<<#a<<":";rep(pachico,n)cout<<" "<<a[pachico];cout<<endl

#define svec(v) cout<<#v<<":";rep(pachico,v.size())cout<<" "<<v[pachico];cout<<endl

#define svecp(v) cout<<#v<<":";each(pachico,v)cout<<" {"<<pachico.first<<":"<<pachico.second<<"}";cout<<endl

#define sset(s) cout<<#s<<":";each(pachico,s)cout<<" "<<pachico;cout<<endl

#define smap(m) cout<<#m<<":";each(pachico,m)cout<<" {"<<pachico.first<<":"<<pachico.second<<"}";cout<<endl



using namespace std;



typedef pair<int,int> P;

typedef pair<ll,ll> pll;

typedef vector<int> vi;

typedef vector<vi> vvi;

typedef vector<ll> vl;

typedef vector<vl> vvl;

typedef vector<double> vd;

typedef vector<P> vp;

typedef vector<string> vs;



const int MAX_N = 100005;



#define T int



class Dijkstra {

public:

	struct edge{

		int to; T cost;

	};

	vector<vector<edge> > G;

	vector<T> d;

	int V;

	using pti = pair<T,int>;

	Dijkstra(int node_size){

		V = node_size;

		G.resize(V),d.resize(V,numeric_limits<T>::max());

	}

	//無向グラフの場合

	void add_edge(int u,int v,T cost){

		G[u].pb((edge){v,cost});

	}

	void solve(int s){

		set<pti> st;

		d[s] = 0;

		st.insert(pti(0,s));

		while(!st.empty()){

			pti p = *(st.begin());

			st.erase(st.begin());

			int v = p.second;

			if(d[v] < p.first) continue;

			for(auto& w : G[v]){

				if(d[w.to] > d[v] + w.cost){

					d[w.to] = d[v] + w.cost;

					st.insert(pti(d[w.to],w.to));

				}

			}

		}

	}

};



int main()

{

    cin.tie(0);

    ios::sync_with_stdio(false);

    int n, m, r;

    cin >> n >> m >> r;

	Dijkstra dj(n);

	rep(i,m){

		int a,b,c;

		cin >> a >> b >> c;

		dj.add_edge(a, b, c);

	}

	dj.solve(r);

	each(val,dj.d){

		if(val == numeric_limits<T>::max()){

			cout << "INF\n";

		}else{

			cout << val << "\n";

		}

	}

    return 0;

}