Problem:
Score : 800 points

Problem Statement

Niwango has N cards, numbered 1,2,\ldots,N.
He will now arrange these cards in a row.

Niwango wants to know if there is a way to arrange the cards while satisfying all the N conditions below.
To help him, determine whether such a way exists. If the answer is yes, also find the lexicographically smallest such arrangement.

To the immediate right of Card 1 (if any) is NOT Card a_1.

To the immediate right of Card 2 (if any) is NOT Card a_2.

\vdots

To the immediate right of Card N (if any) is NOT Card a_N.

Constraints

2 \leq N \leq 10^{5}

1 \leq a_i \leq N

a_i \neq i

Input

Input is given from Standard Input in the following format:

N
a_1 a_2 \ldots a_N

Output

If no arrangements satisfy the conditions, print -1. If such arrangements exist, print the lexicographically smallest such arrangement, in the following format:

b_1 b_2 \ldots b_N

Here, b_i represents the i-th card from the left.

Sample Input 1

4
2 3 4 1

Sample Output 1

1 3 2 4

The arrangement (1,2,3,4) is lexicographically smaller than (1,3,2,4), but is invalid, since it violates the condition "to the immediate right of Card 1 is not Card 2."

Sample Input 2

2
2 1

Sample Output 2

-1

If no arrangements satisfy the conditions, print -1.

Sample Input 3

13
2 3 4 5 6 7 8 9 10 11 12 13 12

Sample Output 3

1 3 2 4 6 5 7 9 8 10 12 11 13

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

use std::collections::{BTreeMap, BTreeSet};

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    if n == 2 {
        println!("-1");
        return;
    }
    let refer: Vec<usize> = (0..n).map(|_| sc.read::<usize>() - 1).collect();
    let mut inv_refer = vec![0; n];
    for i in 0..n {
        inv_refer[refer[i]] += 1;
    }

    let mut map = BTreeMap::new();
    for i in 0..n {
        map.entry(inv_refer[i])
            .or_insert_with(BTreeSet::new)
            .insert(i);
    }

    let mut remain = (0..n).rev().collect::<Vec<_>>();

    let mut is_removed = vec![false; n];
    let mut ans = vec![];
    while ans.len() + 3 < n {
        let highest_reference = *map.iter().next_back().unwrap().0;
        if highest_reference + ans.len() + 1 == n {
            assert_eq!(map[&highest_reference].len(), 1);
            let highest = *map[&highest_reference].iter().next().unwrap();
            ans.push(highest);
            remove(highest, &refer, &mut inv_refer, &mut map, &mut is_removed);
            continue;
        }

        let first = get(&mut remain, &is_removed);
        if ans.len() > 0 && refer[ans[ans.len() - 1]] == first {
            let second = get(&mut remain, &is_removed);
            remain.push(first);
            ans.push(second);
            remove(second, &refer, &mut inv_refer, &mut map, &mut is_removed);
        } else {
            ans.push(first);
            remove(first, &refer, &mut inv_refer, &mut map, &mut is_removed);
        }
    }

    let remain = remain
        .into_iter()
        .filter(|&r| !is_removed[r])
        .collect::<Vec<_>>();
    assert_eq!(remain.len(), 3);

    let mut candidates = vec![
        (remain[0], remain[1], remain[2]),
        (remain[0], remain[2], remain[1]),
        (remain[1], remain[0], remain[2]),
        (remain[1], remain[2], remain[0]),
        (remain[2], remain[1], remain[0]),
        (remain[2], remain[0], remain[1]),
    ];
    candidates.sort();
    for (a1, a2, a3) in candidates.into_iter() {
        if ans.len() > 0 && refer[ans[ans.len() - 1]] == a1 {
            continue;
        }

        if refer[a1] == a2 || refer[a2] == a3 {
            continue;
        }
        ans.push(a1);
        ans.push(a2);
        ans.push(a3);
        break;
    }
    assert_eq!(ans.len(), n);

    for i in 0..n {
        if i > 0 {
            sc.write(" ");
        }
        sc.write(ans[i] + 1);
    }
    sc.write("\n");
}

fn get(v: &mut Vec<usize>, is_removed: &Vec<bool>) -> usize {
    loop {
        let t = v.pop().unwrap();
        if !is_removed[t] {
            return t;
        }
    }
}

fn remove(
    selected: usize,
    refer: &[usize],
    inv_refer: &mut Vec<usize>,
    map: &mut BTreeMap<usize, BTreeSet<usize>>,
    is_removed: &mut Vec<bool>,
) {
    let reference_count = inv_refer[selected];
    let set = map.get_mut(&reference_count).unwrap();
    assert!(set.remove(&selected));
    if set.is_empty() {
        assert!(map.remove(&reference_count).unwrap().is_empty());
    }
    is_removed[selected] = true;

    let refer = refer[selected];
    assert!(inv_refer[refer] > 0);
    let current_count = inv_refer[refer];
    inv_refer[refer] -= 1;
    let next_count = inv_refer[refer];

    if is_removed[refer] {
        return;
    }

    assert!(map.get_mut(&current_count).unwrap().remove(&refer));
    if map[&current_count].is_empty() {
        assert!(map.remove(&current_count).unwrap().is_empty());
    }
    map.entry(next_count)
        .or_insert_with(BTreeSet::new)
        .insert(refer);
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> Self {
        Self(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}