将没有值的下标记录,考虑将未使用的数逆序填充给这些下标,显然最多只有一个点会出现$f[i] = i$的情况,如果遇到了就将这个位置的值与下个位置的值交换,这样必然可以构造一个合法方案。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <set>
using namespace std;
const int N = 200010;
int a[N];
int ne[N], c[N];
int main()
{
int T;
cin >> T;
while (T--)
{
int n;
cin >> n;
vector<int> b;
set<int> S;
for (int i = 1; i <= n; i++) S.insert(i);
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (a[i] == 0)
b.push_back(i);
else S.erase(a[i]);
}
auto it = S.end();
for (auto &x : b)
a[x] = *(-- it);
for (int i = 0; i < b.size(); i++)
if (a[b[i]] == b[i])
swap(a[b[i]], a[b[(i + 1) % b.size()]]);
for (int i = 1; i <= n; i++) cout << a[i] << ' ';
cout << endl;
}
}