【Foreign】置换 [数论][置换]
置换
Time Limit: 10 Sec Memory Limit: 256 MBDescription
![](https://images2015.cnblogs.com/blog/1109445/201703/1109445-20170301205410282-2120390180.png)
Input
![](https://images2015.cnblogs.com/blog/1109445/201703/1109445-20170301205421141-1141817322.png)
Output
![](https://images2015.cnblogs.com/blog/1109445/201703/1109445-20170301205428095-444759966.png)
Sample Input
4
2 1 4 3
Sample Output
3 4 2 1
HINT
1<=n<=10^6
Main idea
已知一个置换置换自己得到的序列,求这个置换。
Solution
显然是置换题。首先我们正向考虑,考虑一下一个置换置换自己会发生怎样的结果。
然后我们一波画图发现:如果一个轮换的长度是奇数,那么这个环所有点连边向后移一位;如果一个轮换的长度数偶数,那么就会拆解成两个长度一样的新轮换。
然后我们倒着来想,考虑如何合并。显然现在的轮换是奇数的话,我们将所有点连边向前移动一位。如果是偶数的话,再找一个长度和这个一样的轮换,把两个轮换并在一起,并在一起就是两个轮换依次取出一个。
如果轮换是偶数且找不到一对的话就显然不合法。
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 #include<cstdio>
5 #include<cstring>
6 #include<cstdlib>
7 #include<vector>
8 #include<cmath>
9 using namespace std;
10
11 const int ONE=1000005;
12
13 int n;
14 int x,P[ONE],d[ONE],record[ONE];
15 int vis[ONE],cnt,tot,num;
16 int Ans[ONE];
17
18 vector <int> q[ONE];
19 struct power
20 {
21 int len;
22 int id;
23 }R[ONE];
24 int cmp(const power &a,const power &b){return a.len < b.len;}
25
26 int get()
27 {
28 int res=1,Q=1;char c;
29 while( (c=getchar())<48 || c>57 )
30 if(c=='-')Q=-1;
31 res=c-48;
32 while( (c=getchar())>=48 && c<=57 )
33 res=res*10+c-48;
34 return res*Q;
35 }
36
37 int main()
38 {
39 n=get();
40 for(int i=1;i<=n;i++) P[i]=get();
41
42 for(int i=1;i<=n;i++)
43 {
44 if(vis[i]) continue;
45 cnt = 0; x = i;
46 for(;;)
47 {
48 record[++cnt]=x;
49 x = P[x];
50 vis[x] = 1;
51 if(x==i) break;
52 }
53
54 if(cnt==1) {Ans[i]=i; continue;}
55
56 if(cnt%2==1)
57 {
58 int len=1;
59 num=0;
60 for(int j=1;j<=cnt;j++)
61 {
62 d[len]=record[j];
63 len+=2; if(len>cnt) len-=cnt;
64 }
65 d[cnt+1]=d[1];
66 for(int j=1;j<=cnt;j++) Ans[d[j]]=d[j+1];
67 }
68 else
69 {
70 R[++tot].id=tot; R[tot].len=cnt;
71 for(int j=1;j<=cnt;j++)
72 q[tot].push_back(record[j]);
73 }
74 }
75
76 if(tot%2==1) {printf("-1");exit(0);}
77 sort(R+1,R+tot+1,cmp);
78
79 for(int j=1;j<=tot;j+=2)
80 {
81 int x=R[j].id, y=R[j+1].id;
82 if(R[j].len != R[j+1].len) {printf("-1");exit(0);}
83
84 num=0;
85 for(int i=0;i<R[j].len;i++)
86 d[++num]=q[x][i], d[++num]=q[y][i];
87
88 d[num+1]=d[1];
89 for(int i=1;i<=num;i++) Ans[d[i]]=d[i+1];
90 }
91
92 for(int i=1;i<=n;i++) printf("%d ",Ans[i]);
93 }