use std::cmp;
use std::cmp::Ordering;
use std::collections::BinaryHeap;
use std::usize;

#[derive(Copy, Clone, Eq, PartialEq)]
struct State {
    cost: usize,
    position: usize,
}

// The priority queue depends on `Ord`.
// Explicitly implement the trait so the queue becomes a min-heap
// instead of a max-heap.
impl Ord for State {
    fn cmp(&self, other: &State) -> Ordering {
        // Notice that the we flip the ordering on costs.
        // In case of a tie we compare positions - this step is necessary
        // to make implementations of `PartialEq` and `Ord` consistent.
        other.cost.cmp(&self.cost)
    }
}

// `PartialOrd` needs to be implemented as well.
impl PartialOrd for State {
    fn partial_cmp(&self, other: &State) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

// Each node is represented as an `usize`, for a shorter implementation.
#[derive(Clone)]
struct Edge {
    node: usize,
    cost: usize,
}

// Dijkstra's shortest path algorithm.

// Start at `start` and use `dist` to track the current shortest distance
// to each node. This implementation isn't memory-efficient as it may leave duplicate
// nodes in the queue. It also uses `usize::MAX` as a sentinel value,
// for a simpler implementation.
fn shortest_path(adj_list: &Vec<Vec<Edge>>, start: usize) -> Vec<usize> {
    // dist[node] = current shortest distance from `start` to `node`
    let mut dist: Vec<_> = (0..adj_list.len()).map(|_| usize::MAX).collect();

    let mut heap = BinaryHeap::new();

    // We're at `start`, with a zero cost
    dist[start] = 0;
    heap.push(State {
        cost: 0,
        position: start,
    });

    // Examine the frontier with lower cost nodes first (min-heap)
    while let Some(State { cost, position }) = heap.pop() {
        // Important as we may have already found a better way
        if cost > dist[position] {
            continue;
        }

        // For each node we can reach, see if we can find a way with
        // a lower cost going through this node
        for edge in &adj_list[position] {
            let next = State {
                cost: cost + edge.cost,
                position: edge.node,
            };

            // If so, add it to the frontier and continue
            if next.cost < dist[next.position] {
                heap.push(next);
                // Relaxation, we have now found a better way
                dist[next.position] = next.cost;
            }
        }
    }

    // Goal not reachable
    dist
}

fn main() {
    let line = read();

    let n = line[0];
    let edges = line[1];
    let start = line[2] - 1;
    let goal = line[3] - 1;

    let mut yen_graph = vec![vec![]; n];
    let mut snuuk_graph = vec![vec![]; n];
    for _ in 0..edges {
        let line = read();
        let u = line[0] - 1;
        let v = line[1] - 1;
        let yen_cost = line[2];
        let snuuk_cost = line[3];
        yen_graph[u].push(Edge {
            node: v,
            cost: yen_cost,
        });
        yen_graph[v].push(Edge {
            node: u,
            cost: yen_cost,
        });

        snuuk_graph[u].push(Edge {
            node: v,
            cost: snuuk_cost,
        });
        snuuk_graph[v].push(Edge {
            node: u,
            cost: snuuk_cost,
        });
    }

    let yen_shortest_path = shortest_path(&yen_graph, start);
    let snuuk_shortest_path = shortest_path(&snuuk_graph, goal);

    let mut ans = vec![0; n];
    let mut current_shortest_distance = usize::MAX;
    for i in (0..n).rev() {
        let shortest_distance_by_yen_to_i = yen_shortest_path[i];
        let shortest_distance_by_snuuk_from_i = snuuk_shortest_path[i];
        let shortest_distance_via_i =
            shortest_distance_by_yen_to_i + shortest_distance_by_snuuk_from_i;
        current_shortest_distance = cmp::min(current_shortest_distance, shortest_distance_via_i);
        ans[i] = current_shortest_distance;
    }

    let start_money = 1e15 as usize;
    for i in 0..n {
        println!("{}", start_money - ans[i]);
    }
}

fn read() -> Vec<usize> {
    let mut buffer = String::new();
    std::io::stdin().read_line(&mut buffer).ok();
    buffer
        .trim()
        .split_whitespace()
        .map(|e| e.parse().ok().unwrap())
        .collect()
}


Measured memory_bytes: 31480