洛谷传送门
Codeforces传送门
题目大意
给定一个 n n n的排列 p i p_i pi, 求一个排列 q i q_i qi, 满足对于 ∀ i ∈ [ 1 , n ] \forall i\in[1,n] ∀i∈[1,n], q q i = p i q_{q_i}=p_i qqi=pi。
解题分析
神奇的规律题…
先尝试着正着推, 从 i i i向 p i p_i pi连一条边, 会构成很多的环。
然后我们发现, 如果设 k i = p p i k_i=p_{p_i} ki=ppi, k i k_i ki再这样连也会构成很多环, 并且有如下关系:
- 如果原来 i i i在一个偶环中, 那么这个偶环会被间隔着分成两个大小相同的环。
- 如果原来 i i i在一个奇环中, 那么环中元素顺序会变成间隔一个位置的元素相邻。
于是找到 p i p_i pi中所有的环, 把大小相同的偶环随便合在一起, 奇环还原一下, 如果最后有单独的偶环则无解。
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <vector>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define MX 1005000
#define gc getchar()
#define ll long long
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
struct INFO {int siz; std::vector <int> ele;} dat[MX];
IN bool operator < (const INFO &x, const INFO &y)
{return x.siz < y.siz;}
std::vector <int> vec;
int n, tot;
bool vis[MX];
int nex[MX], ans[MX], v[MX], seq[MX];
int main(void)
{
in(n);
for (R int i = 1; i <= n; ++i) in(nex[i]);
for (R int i = 1; i <= n; ++i)
{
if (!vis[i])
{
++tot;
int cur = i;
vec.clear();
vis[i] = true;
vec.push_back(i);
W (!vis[nex[cur]])
{
vis[nex[cur]] = true;
vec.push_back(nex[cur]);
cur = nex[cur];
}
dat[tot] = {vec.size(), vec};
}
}
std::sort(dat + 1, dat + 1 + tot);
R int cur = 1;
W (cur <= tot)
{
if (dat[cur].siz & 1)
{
int half = dat[cur].siz + 1 >> 1;
for (R int i = 1; i <= half; ++i) seq[(i << 1) - 1] = dat[cur].ele[i - 1];
for (R int i = half + 1; i <= dat[cur].siz; ++i) seq[(i - half) << 1] = dat[cur].ele[i - 1];
for (R int i = 1; i < dat[cur].siz; ++i) ans[seq[i]] = seq[i + 1];
ans[seq[dat[cur].siz]] = seq[1];
++cur;
}
else
{
if (cur == tot || dat[cur + 1].siz ^ dat[cur].siz) return puts("-1"), 0;
int siz = dat[cur].siz, len = 0;
for (R int i = 0; i < siz; ++i) seq[++len] = dat[cur].ele[i], seq[++len] = dat[cur + 1].ele[i];
for (R int i = 1; i < len; ++i) ans[seq[i]] = seq[i + 1];
ans[seq[len]] = seq[1];
cur += 2;
}
}
for (R int i = 1; i <= n; ++i) printf("%d ", ans[i]);
}