#include <stdio.h>
#include <stdlib.h>
#define MAX_NODES 100000
#define INF 1010001000

typedef struct edge {
    int to, cost;
    struct edge *next;
}edge;

typedef struct vertex {
    int value, edges;
    struct edge *head;
}vertex;

typedef struct pair {
    int f, s;
}pair;

vertex graph[MAX_NODES];
pair queue[MAX_NODES];
int sz, V, E, start;

pair pop(void);
void push(pair x);
void add_edge(int from, int to, int cost);
void dijkstra(int st);


int main(void)
{
    int i, s, t, d;
    pair a;
    scanf("%d %d %d", &V, &E, &start);
    for (i = 0; i < E; i++) {
        scanf("%d %d %d", &s, &t, &d);
        add_edge(s, t, d);
    }
    for (i = 0; i < V; i++) {
        graph[i].value = INF;
    }
    dijkstra(start);
    for (i = 0; i < V; i++) {
        if (graph[i].value == INF) {
            puts("INF");
        } else {
            printf("%d\n", graph[i].value);
        }
    }
    return 0;
}


void dijkstra(int st)
{
    int i, j, v;
    pair tmp;
    edge *now;
    //Queueの初期化
    for (i = 0; i < 100; i++) {
        queue[i].f = INF;
    }
    graph[st].value = 0;

    tmp.f = 0; tmp.s = st;
    push(tmp);

    while (queue[0].f != INF) {
        tmp = pop();
        //printf("poped elements:%d %d\n", tmp.f, tmp.s);
        v = tmp.s;      //現在見ているノードの番号
        now = graph[v].head;
        if (graph[v].value < tmp.f) { 
            continue;
        }
        while (now != NULL) {
            if (graph[now->to].value > graph[v].value + now->cost) {
                //printf("update value: %d to", graph[now->to].value);
                graph[now->to].value = graph[v].value + now->cost;
                //printf(" %d about %d\n", graph[now->to].value, now->to);
                tmp.f = graph[now->to].value; tmp.s = now->to;
                push(tmp);
            }
            now = now->next;
        }
    }
}

void add_edge(int from, int to, int cost)
{
    //fromからtoへ辺を張る
    edge *new, *now = graph[from].head;
    new = (edge *)malloc(sizeof(edge));
    new->to = to;
    new->cost = cost;
    if (now == NULL) {
        graph[from].head = new;
    } else {
        while (now->next != NULL) {
            now = now->next;
        }
        now->next = new;
    }
    graph[from].edges++;
}

void push(pair x)
{
    int i;
    i = sz;
    queue[sz++] = x;
    while (i > 0) {
        if (queue[(i-1)/2].f > x.f) {
            queue[i] = queue[(i-1)/2];
        } else {
            break;
        }
        i = (i-1)/2;
    }
    queue[i] = x;
}

pair pop(void)
{
    int i;
    pair ans = queue[0], tmp;
    queue[0] = queue[sz];
    queue[sz--].f = INF;
    i = 0;
    while (i < sz) {
        if (queue[i].f > queue[i*2+1].f || queue[i].f < queue[i*2+2].f ) {
            if (queue[i*2+1].f < queue[i*2+2].f) {
                tmp = queue[i];
                queue[i] = queue[i*2+1];
                queue[i*2+1] = tmp;
                i = i*2+1;
            } else {
                tmp = queue[i];
                queue[i] = queue[i*2+2];
                queue[i*2+2] = tmp;
                i = i*2+2;
            }
        } else {
            break;
        }
    }
    return ans;
}