Problem: For a given weighted graph G(V, E) and a source r, find the source shortest path to each vertex from the source (SSSP: Single Source Shortest Path).

Constraints

* 1 ≤ |V| ≤ 100000
* 0 ≤ di ≤ 10000
* 0 ≤ |E| ≤ 500000
* There are no parallel edges
* There are no self-loops

Input

An edge-weighted graph G (V, E) and the source r.


|V| |E| r
s0 t0 d0
s1 t1 d1
:
s|E|-1 t|E|-1 d|E|-1


|V| is the number of vertices and |E| is the number of edges in G. The graph vertices are named with the numbers 0, 1,..., |V|-1 respectively. r is the source of the graph.

si and ti represent source and target vertices of i-th edge (directed) and di represents the cost of the i-th edge.

Output

Print the costs of SSSP in the following format.


c0
c1
:
c|V|-1


The output consists of |V| lines. Print the cost of the shortest path from the source r to each vertex 0, 1, ... |V|-1 in order. If there is no path from the source to a vertex, print INF.

Examples

Input

4 5 0
0 1 1
0 2 4
1 2 2
2 3 1
1 3 5


Output

0
1
3
4


Input

4 6 1
0 1 1
0 2 4
2 0 1
1 2 2
3 1 1
3 2 5


Output

3
0
2
INF

Solution (in JAVA):

Solution:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

/**
 * Created by huzhejie on 2016/10/10.
 * dijkstra algorithm for single source shortest path
 */
public class Main {
    /**
     * the main execution part of dijkstra algorithm
     * @param source source vertex
     */
    @SuppressWarnings("unchecked")
    private static void dijkstra(Vertex source){
        source.minDistance = 0;
        PriorityQueue<Vertex> queue = new PriorityQueue<Vertex>();
        queue.add(source);
        while(!queue.isEmpty()){
            Vertex v = queue.poll();
            for(Edge edge:v.nighbors){
                int newDist = v.minDistance +edge.weight;
                /*
                make a comparision with new distance
                 */
                if(edge.target.minDistance>newDist){
                    /*
                    change the value of minDistance of the target vertex of the directed edge
                     */
                    queue.remove(edge.target);
                    edge.target.minDistance = newDist;
                    queue.add(edge.target);
                }
            }
        }
    }

    public static void main(String args[]){
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int l = 1;
        String str;
        /*
        read the data and make the graph
         */
        try {
            str = br.readLine();
            Graph g = new Graph(Integer.parseInt(str.split(" ")[0]));
            int source  = Integer.parseInt(str.split(" ")[2]);
            int edge = Integer.parseInt(str.split(" ")[1]);
            while ((str = br.readLine()) != null&&l<=edge){
                String record[] = str.split(" ");
                g.addEdge(Integer.parseInt(record[0]),Integer.parseInt(record[1]),Integer.parseInt(record[2]));
                l++;
            }
            br.close();
        /*
        execute dijkstra algorithm
         */
            dijkstra(g.vertices.get(source));
        /*
        output the result
        */
            for(Vertex v:g.vertices.values()){
                if(v.minDistance == Integer.MAX_VALUE)
                    System.out.println("INF");
                else
                    System.out.println(v.minDistance);
            }
        }catch (IOException e){
            e.printStackTrace();
        }
    }

}
class Edge{
    /*
    the target vertex of the edge
     */
    public final Vertex target;
    /*
    the weight of the edge
     */
    public final int weight;

    public Edge(Vertex target,int weight){
        this.target = target;
        this.weight = weight;
    }
}
class Graph{
    /*
    the set of the vertices of the graph
     */
    Map<Integer,Vertex> vertices;
    public Graph(int vertexNumber){
        vertices = new LinkedHashMap<Integer, Vertex>();
        for(int i = 0;i<vertexNumber;i++){
            vertices.put(i,new Vertex(i));
        }
    }

    /**
     * add an edge into the graph
     * @param source the start vertex of the edge
     * @param target the target vertex of the edge
     * @param weight the weight of the edge
     */
    public void addEdge(int source,int target,int weight){
        Vertex v = vertices.get(source);
        Edge edge = new Edge(vertices.get(target),weight);
        v.nighbors.add(edge);
    }
}
@SuppressWarnings("unchecked")
class Vertex implements Comparable<Vertex>{
    /*
    the id of vertex
     */
    int id;
    /*
    minimal distance from the source to this vertex
     */
    int minDistance = Integer.MAX_VALUE;
    /*
    stores edges whose start vertex's id equals to this vertex's id
     */
    ArrayList<Edge> nighbors;

    public Vertex(int id){
        this.id = id;
        this.nighbors = new ArrayList<Edge>();
    }
    public int compareTo(Vertex o) {
        return Integer.compare(minDistance,o.minDistance);
    }
}