Problem:
Single Source Shortest Path

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).

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.

Constraints

1 ≤ |V| ≤ 100000

0 ≤ di ≤ 10000

0 ≤ |E| ≤ 500000

There are no parallel edges

There are no self-loops

Sample Input 1

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

Sample Output 1

0
1
3
4

Sample Input 2

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

Sample Output 2

3
0
2
INF

Solution in Rust (judge verdict: Time Limit Exceeded)

use std::collections::BinaryHeap;
use std::cmp::*;

// use graph::graph::*;

pub type Weight = i32;

#[derive(Clone, Hash, Debug, Default)]
pub struct Edge {
    pub src: usize,
    pub dst: usize,
    pub weight: Weight,
}

impl Edge {
    fn new(src: usize, dst: usize, weight: Weight) -> Edge {
        Edge {
            src: src,
            dst: dst,
            weight: weight
        }
    }
}

pub type Edges = Vec<Edge>;
pub type Graph = Vec<Edges>;

pub fn add_weighted_arc(graph: &mut Graph, src: usize, dst: usize, weight: Weight) {
    graph[src].push(Edge::new(src, dst, weight));
}

pub fn add_weighted_edge(graph: &mut Graph, src: usize, dst: usize, weight: Weight) {
    add_weighted_arc(graph, src, dst, weight);
    add_weighted_arc(graph, dst, src, weight);
}

pub fn add_arc(graph: &mut Graph, src: usize, dst: usize) {
    add_weighted_arc(graph, src, dst, 1);
}

pub fn add_edge(graph: &mut Graph, src: usize, dst: usize) {
    add_weighted_edge(graph, src, dst, 1);
}

#[derive(PartialEq, Eq, Clone, Copy)]
struct DijkstraState(usize, Weight);

impl Ord for DijkstraState {
    fn cmp(&self, other: &DijkstraState) -> Ordering {
        other.1.cmp(&self.1)
    }
}

impl PartialOrd for DijkstraState {
    fn partial_cmp(&self, other: &DijkstraState) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

pub fn dijkstra(graph: &Graph, src: usize) -> Vec<Option<Weight>> {
    let inf = Weight::max_value() / 2;
    let n = graph.len();
    let mut heap = BinaryHeap::<DijkstraState>::with_capacity(n);
    heap.push(DijkstraState(src, 0));
    let mut dist = vec![inf; n];
    dist[src] = 0;
    while let Some(DijkstraState(v, d)) = heap.pop() {
        if dist[v] == d {
            for e in graph[v].iter() {
                if dist[e.dst] > d + e.weight {
                    dist[e.dst] = d + e.weight;
                    heap.push(DijkstraState(e.dst, dist[e.dst]));
                }
            }
        }
    }
    dist.iter().map(|&d| if d != inf { Some(d) } else { None }).collect()
}

pub fn dijkstra_to(graph: &Graph, src: usize, dst: usize) -> Option<Weight> {
    let inf = Weight::max_value() / 2;
    if src == dst {
        Some(0)
    } else {
        let mut heap = BinaryHeap::new();
        heap.push(DijkstraState(src, 0));
        let mut dist = vec![inf; graph.len()];
        dist[src] = 0;
        let mut res = None;
        while let Some(DijkstraState(v, d)) = heap.pop() {
            if v == dst {
                res = Some(d);
                break;
            }
            if dist[v] == d {
                for e in graph[v].iter() {
                    if dist[e.dst] > d + e.weight {
                        dist[e.dst] = d + e.weight;
                        heap.push(DijkstraState(e.dst, dist[e.dst]));
                    }
                }
            }
        }
        res
    }
}

pub fn bidirectional_dijkstra(graph: &Graph, src: usize, dst: usize) -> Option<Weight> {
    if src == dst {
        Some(0)
    } else {
        let inf: Weight = Weight::max_value() / 2;

        let n = graph.len();
        let mut heaps = BinaryHeap::with_capacity(n);
        let mut heapd = BinaryHeap::with_capacity(n);
        heaps.push(DijkstraState(src, 0));
        heapd.push(DijkstraState(dst, 0));
        let mut dists = vec![inf; n];
        let mut distd = vec![inf; n];
        dists[src] = 0;
        distd[dst] = 0;

        let mut mu = inf;

        while let Some((DijkstraState(v, d), heap, dist, dist_)) = {
            let ds = heaps.peek().unwrap_or(&DijkstraState(0, inf)).1;
            let dd = heapd.peek().unwrap_or(&DijkstraState(0, inf)).1;
            if ds + dd >= mu {
                None
            } else if ds <= dd {
                heaps.pop().map(|x| (x, &mut heaps, &mut dists, &mut distd)) 
            } else {
                heapd.pop().map(|x| (x, &mut heapd, &mut distd, &mut dists)) 
            }
        } {
            if dist[v] == d {
                for e in graph[v].iter() {
                    if dist[e.dst] > d + e.weight {
                        dist[e.dst] = d + e.weight;
                        heap.push(DijkstraState(e.dst, dist[e.dst]));
                        mu = min(mu, dist[e.dst] + dist_[e.dst]);
                    }
                }
            }
        }

        if mu != inf {
            Some(mu)
        } else {
            None
        }
    }
}

pub fn directed_bidirectional_dijkstra(graph: &Graph, src: usize, dst: usize) -> Option<Weight> {
    if src == dst {
        Some(0)
    } else {
        let inf: Weight = Weight::max_value() / 2;

        let n = graph.len();

        let mut rev_graph = vec![vec![]; n];
        for es in graph.iter() {
            for e in es.iter() {
                add_weighted_arc(&mut rev_graph, e.dst, e.src, e.weight);
            }
        }
        let mut heaps = BinaryHeap::with_capacity(n);
        let mut heapd = BinaryHeap::with_capacity(n);
        heaps.push(DijkstraState(src, 0));
        heapd.push(DijkstraState(dst, 0));
        let mut dists = vec![inf; n];
        let mut distd = vec![inf; n];
        dists[src] = 0;
        distd[dst] = 0;

        let mut mu = inf;

        while let Some((DijkstraState(v, d), heap, dist, dist_, grp)) = {
            let ds = heaps.peek().unwrap_or(&DijkstraState(0, inf)).1;
            let dd = heapd.peek().unwrap_or(&DijkstraState(0, inf)).1;
            if ds + dd >= mu {
                None
            } else if ds <= dd {
                heaps.pop().map(|x| (x, &mut heaps, &mut dists, &mut distd, graph)) 
            } else {
                heapd.pop().map(|x| (x, &mut heapd, &mut distd, &mut dists, &rev_graph)) 
            }
        } {
            if dist[v] == d {
                for e in grp[v].iter() {
                    if dist[e.dst] > d + e.weight {
                        dist[e.dst] = d + e.weight;
                        heap.push(DijkstraState(e.dst, dist[e.dst]));
                        mu = min(mu, dist[e.dst] + dist_[e.dst]);
                    }
                }
            }
        }

        if mu != inf {
            Some(mu)
        } else {
            None
        }
    }
}

// // https://abc012.contest.atcoder.jp/tasks/abc012_4
// use std::io::*;

// fn read(s: &mut StdinLock) -> Weight {
//     s.bytes()
//         .map(|c| c.expect("failed to read char") as char) 
//         .skip_while(|c| c.is_whitespace())
//         .take_while(|c| !c.is_whitespace())
//         .fold(0, |acc, x| acc * 10 + (x as u8 - b'0') as Weight)
// }

// fn main() {
//     let stdin = stdin();
//     let mut stdin = stdin.lock();
//     let stdin = &mut stdin;

//     let n = read(stdin) as usize;
//     let m = read(stdin) as usize;
//     let mut g = vec![vec![]; n];
//     for _ in 0..m {
//         let a = read(stdin) as usize - 1;
//         let b = read(stdin) as usize - 1;
//         let c = read(stdin);
//         add_weighted_edge(&mut g, a, b, c);
//     }

//     let inf = 1000000000;
//     let mut res = inf;
//     for i in 0..n {
//         let mut cand = 0;
//         for j in 0..n {
//             let d = bidirectional_dijkstra(&g, i, j).unwrap_or(inf);
//             cand = max(cand, d);
//             if cand > res {
//                 break;
//             }
//         }
//         res = min(res, cand);
//     }
//     println!("{}", res);
// }

// // http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A&lang=jp
// use std::io::*;

// fn read(s: &mut StdinLock) -> Weight {
//     s.bytes()
//         .map(|c| c.expect("failed to read char") as char) 
//         .skip_while(|c| c.is_whitespace())
//         .take_while(|c| !c.is_whitespace())
//         .fold(0, |acc, x| acc * 10 + (x as u8 - b'0') as Weight)
// }

// fn main() {
//     let stdin = stdin();
//     let mut stdin = stdin.lock();
//     let stdin = &mut stdin;

//     let n = read(stdin) as usize;
//     let m = read(stdin) as usize;
//     let r = read(stdin) as usize;
//     let mut g = vec![vec![]; n];
//     for _ in 0..m {
//         let a = read(stdin) as usize;
//         let b = read(stdin) as usize;
//         let c = read(stdin);
//         add_weighted_arc(&mut g, a, b, c);
//     }

//     let mut s = String::new();
//     let d = dijkstra(&g, r);
//     for e in d.iter() {
//         if let Some(d) = *e {
//             s += d.to_string().as_str();
//         } else {
//             s += "INF";
//         }
//         s += "\n";
//     }
//     print!("{}", s);
// }

// // https://abc012.contest.atcoder.jp/tasks/abc012_4
// use std::io::*;

// fn read(s: &mut StdinLock) -> Weight {
//     s.bytes()
//         .map(|c| c.expect("failed to read char") as char) 
//         .skip_while(|c| c.is_whitespace())
//         .take_while(|c| !c.is_whitespace())
//         .fold(0, |acc, x| acc * 10 + (x as u8 - b'0') as Weight)
// }

// fn main() {
//     let stdin = stdin();
//     let mut stdin = stdin.lock();
//     let stdin = &mut stdin;

//     let n = read(stdin) as usize;
//     let m = read(stdin) as usize;
//     let mut g = vec![vec![]; n];
//     for _ in 0..m {
//         let a = read(stdin) as usize - 1;
//         let b = read(stdin) as usize - 1;
//         let c = read(stdin);
//         add_weighted_edge(&mut g, a, b, c);
//     }

//     let inf = 1000000000;
//     let mut res = inf;
//     for i in 0..n {
//         let dist = (0..n).map(|j| bidirectional_dijkstra(&g, i, j))
//             .map(|d| d.unwrap_or(inf)).max().unwrap();
//         if res > dist {
//             res = dist;
//         }
//     }
//     println!("{}", res);
// }

// http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A&lang=jp
use std::io::*;
fn read(s: &mut StdinLock) -> Weight {
    s.bytes()
        .map(|c| c.expect("failed to read char") as char) 
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .fold(0, |acc, x| acc * 10 + (x as u8 - b'0') as Weight)
}

fn main() {
    let stdin = stdin();
    let mut stdin = stdin.lock();
    let stdin = &mut stdin;

    let n = read(stdin) as usize;
    let m = read(stdin) as usize;
    let r = read(stdin) as usize;
    let mut g = vec![vec![]; n];
    for _ in 0..m {
        let a = read(stdin) as usize;
        let b = read(stdin) as usize;
        let c = read(stdin);
        add_weighted_arc(&mut g, a, b, c);
    }

    let mut buf = String::new();
    for i in 0..n {
        let dist = directed_bidirectional_dijkstra(&g, r, i);
        if let Some(d) = dist {
            buf += d.to_string().as_str();
        } else {
            buf += "INF";
        }
        buf += "\n";
    }
    print!("{}", buf);
}