错误原因
简单认为当前位置的下一个位置一定是可以放的,故将其直接放入优先队列
可看以下三组数据
10
-1 -1 -1 -1 24 5 6 7 14 -1
10
19 101 -1 -1 24 -1 -1 -1 8 9
10
-1 -1 -1 3 14 5 6 7 13 -1
正确思路
1. 可以先把hash值等于所在位置的数放入优先队列 ,类似于拓扑排序
2. 当从优先队列取出一个元素后,将当前位置所在位置的连通块与下一个位置所在连通块连接,使用并查集来处理
3. 判断连接之后的根节点是否能够放入优先队列,能够放入当根节点值不为-1且未被放入过优先队列且根节点值的哈希值的根节点等于根节点
正确代码
#include <bits/stdc++.h>
#define FastIO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> PII;
const char sp = 32, cr = 10;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 5, M = 1e5;
int a[N], n, fa[N], ans[N], cnt;
bool vis[N]; //标记每个点只能入队列一次
priority_queue<PII, vector<PII>, greater<PII>> pq;
int find(int x) {
return fa[x] == x ? x : fa[x] = find(fa[x]);
}
int main() {
int t;
cin >> t;
while (t--) {
memset(a, 0xff, sizeof(a));
memset(vis, 0, sizeof(vis));
cin >> n;
cnt = 0;
for (int i = 0;i < n;++i) cin >> a[i];
int num = 0;
for (int i = 0;i < n;++i) {
fa[i] = i;
if (a[i] != -1) ++num;
if (a[i] != -1 && a[i] % n == i) {
vis[i] = true;
pq.push({ a[i],i });
}
}
while (!pq.empty()) {
PII pii = pq.top();pq.pop();
int x = pii.first, y = pii.second;
ans[cnt++] = x;
int p = fa[find(y)] = fa[find((y + 1) % n)]; //将当前块与下一个块链接起来
//首先保证下个位置不为空,然后是没有入过队列,最后是从本来位置到下个位置连通,说明下个位置能放
if (a[p] != -1 && !vis[p] && find(a[p] % n) == p) {
vis[p] = true;
pq.push({ a[p],p });
}
}
if (cnt < num) cout << -1; //此时出现了一些不在其本来位置并且前面存在空位的数字,这是无法达到的
else for (int i = 0;i < cnt;++i) cout << ans[i] << sp;
cout << cr;
}
return 0;
}