Problem:
Score : 500 points

Problem Statement

There is a rooted tree (see Notes) with N vertices numbered 1 to N.
Each of the vertices, except the root, has a directed edge coming from its parent.
Note that the root may not be Vertex 1.

Takahashi has added M new directed edges to this graph.
Each of these M edges, u \rightarrow v, extends from some vertex u to its descendant v.

You are given the directed graph with N vertices and N-1+M edges after Takahashi added edges.
More specifically, you are given N-1+M pairs of integers, (A_1, B_1), ..., (A_{N-1+M}, B_{N-1+M}), which represent that the i-th edge extends from Vertex A_i to Vertex B_i.

Restore the original rooted tree.

Notes

For "tree" and other related terms in graph theory, see the article in Wikipedia, for example.

Constraints

3 \leq N

1 \leq M

N + M \leq 10^5

1 \leq A_i, B_i \leq N

A_i \neq B_i

If i \neq j, (A_i, B_i) \neq (A_j, B_j).

The graph in input can be obtained by adding M edges satisfying the condition in the problem statement to a rooted tree with N vertices.

Input

Input is given from Standard Input in the following format:

N M
A_1 B_1
:
A_{N-1+M} B_{N-1+M}

Output

Print N lines.
In the i-th line, print 0 if Vertex i is the root of the original tree, and otherwise print the integer representing the parent of Vertex i in the original tree.

Note that it can be shown that the original tree is uniquely determined.

Sample Input 1

3 1
1 2
1 3
2 3

Sample Output 1

0
1
2

The graph in this input is shown below:

It can be seen that this graph is obtained by adding the edge 1 \rightarrow 3 to the rooted tree 1 \rightarrow 2 \rightarrow 3.

Sample Input 2

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

Sample Output 2

6
4
2
0
6
2

Solution in Rust (1.15.1) (judge verdict: Accepted)

#[allow(unused)]
use std::io::Write;

#[allow(unused)]
macro_rules! debug {
    ($($format:tt)*) => (write!(std::io::stderr(), $($format)*).unwrap());
}
#[allow(unused)]
macro_rules! debugln {
    ($($format:tt)*) => (writeln!(std::io::stderr(), $($format)*).unwrap());
}

fn main() {
    let (n, m): (usize, usize) = {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).unwrap();
        let s = s.trim_right().to_owned();
        let mut ws = s.split_whitespace();
        let a = ws.next().unwrap().parse().unwrap();
        let b = ws.next().unwrap().parse().unwrap();
        (a, b)
    };

    let mut v: Vec<(usize, usize)> = Vec::new();
    for _ in 0..(n - 1 + m) {
        let v_i = {
            let mut s = String::new();
            std::io::stdin().read_line(&mut s).unwrap();
            let s = s.trim_right().to_owned();
            let mut ws = s.split_whitespace();
            let a = ws.next().unwrap().parse().unwrap();
            let b = ws.next().unwrap().parse().unwrap();
            (a, b)
        };
        v.push(v_i)
    }

    // 0-originに変換して考える
    // 最後に1を足す！！！

    let mut graph_list: Vec<Vec<usize>> = vec![vec![]; n];
    for (a, b) in v {
        graph_list[a - 1].push(b - 1)
    }

    let sorted = topological_sort(&graph_list);
    debugln!("sorted: {:?}", sorted);
    let mut sorted_index = vec![0; n];
    for (i, vertex) in sorted.iter().enumerate() {
        sorted_index[*vertex] = i;
    }
    debugln!("sorted_index: {:?}", sorted_index);

    let ans = dfs(sorted[0], &graph_list, &sorted_index);
    for a in ans {
        // 最後に1を足す
        println!("{}", a + 1);
    }
}

fn topological_sort(graph_list: &[Vec<usize>]) -> Vec<usize> {
    let n = graph_list.len();

    let mut incoming_num = vec![0; n];
    for edges in graph_list.iter() {
        for &vertex in edges {
            incoming_num[vertex] += 1;
        }
    }

    // 入次数0の頂点集合
    let mut stack: Vec<usize> = vec![];
    for (vertex, &num) in incoming_num.iter().enumerate() {
        if num == 0 {
            stack.push(vertex);
        }
    }

    let mut ret = vec![];
    while let Some(vertex) = stack.pop() {
        ret.push(vertex);
        for &next in &graph_list[vertex] {
            incoming_num[next] -= 1;
            if incoming_num[next] == 0 {
                stack.push(next);
            }
        }
    }
    ret
}

// 深さ優先探索（再帰）
fn dfs(start: usize, graph_list: &[Vec<usize>], sorted_index: &Vec<usize>) -> Vec<isize> {
    let n = graph_list.len();
    let mut visited = vec![false; n];
    let mut ans = vec![-1; n];

    dfs_aux(start, graph_list, &mut visited, &mut ans, sorted_index);
    ans
}
// 補助関数
fn dfs_aux(start: usize, graph_list: &[Vec<usize>], visited: &mut Vec<bool>, ans: &mut Vec<isize>, sorted_index: &Vec<usize>) {
    visited[start] = true;

    debugln!("visit {}", start);

    for &next in &graph_list[start] {
        debugln!("ans[{}] = {}, sorted_index[{}] = {}", next, ans[next], start, sorted_index[start]);
        if ans[next] < 0 {
            ans[next] = start as isize;
        } else if sorted_index[ans[next] as usize] < sorted_index[start] {
            ans[next] = start as isize;
        }
        if !visited[next] {
            dfs_aux(next, &graph_list, visited, ans, sorted_index);
        }
    }
}