Codeforces 612E - Square Root of Permutation

来源:互联网 发布:测手速软件 编辑:程序博客网 时间:2024/06/05 00:32

E. Square Root of Permutation

A permutation of length n is an array containing each integer from 1 to n exactly once. For example, q = [4, 5, 1, 2, 3] is a permutation. For the permutation q the square of permutation is the permutation p that p[i] = q[q[i]] for each i = 1… n. For example, the square of q = [4, 5, 1, 2, 3] is p = q^2 = [2, 3, 4, 5, 1].

This problem is about the inverse operation: given the permutation p you task is to find such permutation q that q^2 = p. If there are several such q find any of them.
Input

The first line contains integer n (1 ≤ n ≤ 106) — the number of elements in permutation p.

The second line contains n distinct integers p1, p2, …, pn (1 ≤ pi ≤ n) — the elements of permutation p.
Output

If there is no permutation q such that q2 = p print the number “-1”.

If the answer exists print it. The only line should contain n different integers qi (1 ≤ qi ≤ n) — the elements of the permutation q. If there are several solutions print any of them.
Sample test(s)
Input

4
2 1 4 3

Output

3 4 2 1

Input

4
2 1 3 4

Output

-1

Input

5
2 3 4 5 1

Output

4 5 1 2 3

  • 置换的预备知识:->表示映射关系
    (a1,a2,a3)表示a1->a2,a2->a3,a3->a1;注意这和题目上给的位置对应的关系不一样,即并不是1->a1,2->a2那种;所以这需要将题目给的信息转换成这种置换关系;(下面没特别说明就是指置换而不是题目给的对应关系)
    对于一个置换(a1…an)一定可以划分为若干个不相交的循环,如样例1给的
    (2,1,4,3) 变成置换之后为(1,2)(3,4)
    **3.循环乘法之间的运算:

    • 对于循环里面的元素为奇数个时,(a[1],a[2],a[3])(a[1],a[2],a[3]) = (a[1],a[3],a[2]);即 a[1]->a[2]->a[3] ==>a[1]->a[3];同理a[2]->a[3]->a[1] ==>a[2]->a[1]; a[3] ->a[2];扩展到size = 2k+1个数的循环相乘呢?很容易知道当下标从0开始时;每个数的位置变成了2*i%size;同时告诉我们,循环的大小为奇数时,可以由自己生成,所以不用去管奇数的是否配对;
    • 为偶数时:如(a1,a2,a3,a4)^2 = (a1,a3)(a2,a4);这就告诉我们,当p中分解出来的一个循环的大小为偶数时,循环只能由一个2*n的循环分裂得到,同时会得到另一个大小也为n的循环(这是无解的判断);也可以从上面的例子看出偶数循环分裂的规律;即奇偶分裂;
  • 编码:先使用循环分解算法将对应关系转换为若干个不相交的循环,使用vector存储,为了方面读取每个循环的size();之后按循环大小排序,这里开始认为偶数次同等大小的循环叠加以后以为还要倍增叠加,其实是想多了;因为这里只是置换 的平方;所以直接用ans[位置] = value;(转化为题目要的东西即可);
#include<bits/stdc++.h>using namespace std;const int MAXN = 1e6+10;int B[MAXN],vis[MAXN],ans[MAXN],id[MAXN];vector<int> v[MAXN];#define pb push_backbool cmp(const vector<int> &a,const vector<int> &b){    return a.size() < b.size();}int main(){    int i,n,cnt = 0,tot = 0;    cin>>n;    for(i = 1;i <= n;i++)        scanf("%d",B+i);    for(i = 1;i <= n;i++)if(vis[i] != 1){        int tmp = i;        ++cnt;        do{            vis[tmp] = 1;            v[cnt].pb(tmp);            tmp = B[tmp];        }while(tmp != i);    }    sort(v+1,v+1+cnt,cmp);    for(i = 1;i <= cnt;i++){        int sz = v[i].size();        if(sz & 1){            for(int k = 0;k < sz;k++)                id[k*2%sz] = v[i][k];            for(int k = 0;k < sz;k++)                ans[id[k]] = id[(k+1)%sz];        }        else if(sz == v[i+1].size()){               for(int k = 0;k < sz;k++){                ans[v[i][k]] = v[i+1][k];                ans[v[i+1][k]] = v[i][(k+1)%sz];            }            i++;        }        else{            return puts("-1"),0;        }    }    for(i = 1;i <= n;i++){        printf("%d ",ans[i]);    }}
    -
0 0
原创粉丝点击