1790C: Premutation

This is a simple bruteforce deduction problem. We need to deduce a permutation of elements [1, n] for some integer n from a set of clues. The clues are n snapshots of the permutation where, each with a different element of the permutation missing. These snapshots of the permutation give us two possible values for each position in the permutation. Being as each element in the permutation is only missing in one of the n snapshots, we can use the frequencies with which a value appears at a given position to reconstruct the permutation.

Our deduction starts by noting that we can immediately conclude the correct starting and ending elements from the permutation. In both cases, we will see the correct starting and ending elements n-1 times in the snapshots. So, we settle that the correct first element is the value that appeared most in that position in the snapshots. That means the other value that appeared in that position must appear wherever else it appeared in the snapshots. This will set off a chain of conclusions that will leave us to simply fill in the last element, which we know already.


_83
#include <iostream>
_83
#include <vector>
_83
#include <map>
_83
#include <set>
_83
#include <functional>
_83
_83
void solve() {
_83
int n;
_83
std::cin >> n;
_83
std::vector<std::map<int,int>> possibilities (n);
_83
std::map<int, std::set<int>> holding;
_83
_83
for (int i = 0; i < n; ++i) {
_83
for (int pos = 0; pos < n-1; ++pos) {
_83
int x;
_83
std::cin >> x;
_83
holding[x].insert(pos);
_83
possibilities[pos][x]++;
_83
}
_83
}
_83
_83
std::vector<bool> seen (n, false);
_83
std::vector<int> perm (n, -1);
_83
_83
std::function<void(int,int)> settle_by_deduction = [&] (int pos, int val) {
_83
perm[pos] = val;
_83
_83
int other_val = [&] {
_83
for (auto [candidate, _] : possibilities[pos]) {
_83
if (candidate != val) return candidate;
_83
}
_83
return -1;
_83
}();
_83
_83
if (other_val == -1) return;
_83
_83
int other_pos = [&] {
_83
for (int other : holding[other_val]) {
_83
if (other != pos) return other;
_83
}
_83
return -1;
_83
}();
_83
_83
if (other_pos == -1) return;
_83
_83
seen[pos] = true;
_83
_83
if (!seen[other_pos])
_83
settle_by_deduction(other_pos, other_val);
_83
};
_83
_83
auto most_freq_at = [&] (int idx) {
_83
int best = -1;
_83
int val;
_83
_83
for (auto [candidate, cnt] : possibilities[idx]) {
_83
if (cnt > best) {
_83
best = cnt;
_83
val = candidate;
_83
}
_83
}
_83
_83
return val;
_83
};
_83
_83
settle_by_deduction(0, most_freq_at(0));
_83
settle_by_deduction(n-1, most_freq_at(n-2));
_83
_83
for (int x : perm) {
_83
std::cout << x << ' ';
_83
}
_83
std::cout << '\n';
_83
}
_83
_83
_83
int main() {
_83
int t;
_83
std::cin >> t;
_83
for (int tc = 1; tc <= t; ++tc) {
_83
solve();
_83
}
_83
return 0;
_83
}

If you found this solution helpful, consider leaving a star!