CodeForces 612E Square Root of Permutation

Luo Gu title page Portal & codeforces title page Portal

Define a \ (1 \ sim n \) arranged \ (A \) square \ (A ^ 2 = B \) , if and only if \ (\ forall i \ in [ 1, n], b_i = a_ { } a_i \) , i.e. \ (a ^ 2 \) is the \ (a \) in \ ([1,2, \ cdots, n] \) mappings on \ (2 \) arranged times obtained. Now given a \ (1 \ sim n \) arranged \ (A \) , find \ (B \) such that \ (A = B ^ 2 \) , i.e., find \ (A \) the square root. If multiple solutions, output any one. If there is no solution, output \ (--1 \) .

\ (n \ LE10 6 ^ \) .

See the subject on the map, the first thought into graph theory. \ (\ FORALL I \ in [. 1, n-] \) , from \ (I \) to \ (a_i \) build a directed edge, to obtain a directed graph \ (G = (V = [ 1, n ], E = \ {(X, Y) \ Y = MID a_x \}) \) . Obviously, for a certain arrangement of FIG built out is composed of several rings, since the degree of each node, the degree of both \ (1 \) . Then the \ (a \) after the square, each node will point to its original node node pointed to the original point. After considering the square of each ring, what will become: Obviously, if this ring size is odd, it is still an odd ring; even if this ring size is, it will split into \ (2 \) one half of the original size ring.

Now we have \ (A \) of FIG, it needs to restore the square root based on the deformation law. Consider each ring, divided \ (2 \) cases:

  1. Size is odd. It (a \) \ the square root of the figure is likely to have been an odd ring, it may be caused by a split ring out even half;
  2. Size is even. It (A \) \ square root of the drawing can not be a singular ring, only a size \ (4 \) is an even multiple of half ring splinter.

Clearly, the situation is to be merged are \ (2 \) of the same size ring merger, so that different sized rings are independent of each other, we can restore considered separately for each size. Points \ (2 \) cases:

  1. Size is odd. Then the size of its own each ring either reduction or a ring is to find another merger. Obviously their reduction is unconditional, we greedily choose its own to restore each ring (each node point node is a node in the root node pointing to FIG node points);
  2. Size is even. At this time, the size of each of its ring one ring can be combined to find another. If it is then the number of ring size is odd, then can not be paired off directly outputs \ (- 1 \) leave; otherwise, any combination twenty-two combining (merging the \ (2 \) both in ring any find a starting point and then \ ((1,1) \ to (2,1) \ to (1,2) \ to (2,2 &) \ to (l, 3) \ to \ cdots \) (where \ ((x, y) \) represents the \ (X \) of each ring, the number of starts from the starting point \ (Y \) nodes) as the square root of the ring).

Each access node is normally several times, the time complexity is \ (\ mathrm O (n-) \) .

Paste the code below:

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
void read(int &x){//快读 
    x=0;char c=getchar();
    while(!isdigit(c))c=getchar();
    while(isdigit(c))x=(x<<3)+(x<<1)+(c^48),c=getchar();
}
void prt(int x){//快写 
    if(x>9)prt(x/10);
    putchar(x%10^48);
}
const int N=1000000;
int n; 
int a[N+1];//平方之后的排列 
bool vis[N+1];//DFS时的标记数组 
vector<int> v;//此SCC(环)中的点 
void dfs(int x){//DFS 
    if(vis[x])return;
    vis[x]=true;
    v.pb(x);
    dfs(a[x]);
}
vector<vector<int> > vv;//所有环 
vector<int> havsz[N+1];//大小为[i]的所有环的编号 
int ans[N+1];//a的平方根 
int main(){
    read(n);
    for(int i=1;i<=n;i++)read(a[i]);
    for(int i=1;i<=n;i++)if(!vis[i]){//找出每个环 
        v.clear();
        dfs(i);
        if(v.size()&1){//如果是奇环直接自己还原 
            vector<int> v0(v.size());//还原之后的环 
            for(int j=0,now=0;j<v.size();j++,(now+=2)%=v.size())v0[now]=v[j];
            for(int j=0;j<v.size();j++)ans[v0[j]]=v0[(j+1)%v.size()];//将还原之后的环用排列的形式存到a的平方根里 
        }
        else vv.pb(v);//否则存下来等到后面找其他环合并 
    }
    for(int i=0;i<vv.size();i++)havsz[vv[i].size()].pb(i); 
    for(int i=2;i<=n;i+=2)//枚举偶数大小 
        if(havsz[i].size()&1)return puts("-1"),0;//不能两两配对 
        else for(int j=0;j<havsz[i].size();j+=2){//枚举环对 
            vector<int> &v0=vv[havsz[i][j]]/*第1个环*/,&v1=vv[havsz[i][j+1]]/*第2个环*/,v2(2*v0.size())/*还原之后的环*/;
            for(int k=0,now=0;k<v0.size();k++,now+=2)v2[now]=v0[k],v2[now+1]=v1[k];
            for(int k=0;k<v2.size();k++)ans[v2[k]]=v2[(k+1)%v2.size()];//将还原之后的环用排列的形式存到a的平方根里
        }
    for(int i=1;i<=n;i++)prt(ans[i]),putchar(' ');//输出答案 
    return 0;
}

Guess you like

Origin www.cnblogs.com/ycx-akioi/p/CodeForces-612E.html