【Foreign】置换 [数论][置换]

置换

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  4
  2 1 4 3

Sample Output

  3 4 2 1

HINT

  1<=n<=10^6

Main idea

  已知一个置换置换自己得到的序列,求这个置换。

Solution

  显然是置换题。首先我们正向考虑,考虑一下一个置换置换自己会发生怎样的结果。

  然后我们一波画图发现:如果一个轮换的长度是奇数,那么这个环所有点连边向后移一位;如果一个轮换的长度数偶数,那么就会拆解成两个长度一样的新轮换。

  然后我们倒着来想,考虑如何合并。显然现在的轮换是奇数的话,我们将所有点连边向前移动一位。如果是偶数的话,再找一个长度和这个一样的轮换,把两个轮换并在一起,并在一起就是两个轮换依次取出一个。

  如果轮换是偶数且找不到一对的话就显然不合法。

Code

 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 }
View Code
原文地址:https://www.cnblogs.com/BearChild/p/6486319.html