CodeForces - 441D: Valera and Swaps(置換群)
A permutation p of length n is a sequence of distinct integers p1, p2, ..., pn (1 ≤ pi ≤ n). A permutation is an identity permutation, if for any i the following equation holds pi = i.
A swap (i, j) is the operation that swaps elements p
Valera wonders, how he can transform permutation p into any permutation q, such that f(q) = m, using the minimum number of swaps. Help him do that.
Input
The first line contains integer n (1 ≤ n ≤ 3000) — the length of permutation p. The second line contains n distinct integers p1, p2, ..., pn (1 ≤ pi ≤ n) — Valera‘s initial permutation. The last line contains integer m
In the first line, print integer k — the minimum number of swaps.
In the second line, print 2k integers x1, x2, ..., x2k — the description of the swap sequence. The printed numbers show that you need to consecutively make swaps (x1, x2), (x3, x4), ..., (x2k - 1, x2k).
If there are multiple sequence swaps of the minimum length, print the lexicographically minimum one.
Examples Input5Output
1 2 3 4 5
2
2Input
1 2 1 3
5Output
2 1 4 5 3
2
1Note
1 2
Sequence x1, x2, ..., xs is lexicographically smaller than sequence y1, y2, ..., ys, if there is such integer r (1 ≤ r ≤ s), that x1 = y1, x2 = y2, ..., xr - 1 = yr - 1 and xr < yr.
題意:有函數f(p),表示把排列p,變為順序的排列,所用的最小交換次數,這裏的交換是兩兩交換,而不是相鄰交換。
現在給你排列p和m,讓你交換最小的次數,使得排列變為q,滿足f(q)=m,如果有多種交換方案,輸出字典序最小的;
思路:1,把排列p變為1,2,3....p,的最小次數=N-環數。假如N-環數<m,那就加環。 否則減環。
2,如果交換兩個不在同一個環的位置的數,那麽環數+1;
3,如果交換在同一個環的位置的數,那麽環數-1;
所以我們的任務就是加環或者減環,而每次分組的復雜度是O(N);我們最多加N次環,所以我們可以暴力交換,交換後重新分組。
復雜度O(N^2);
#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=3010; int a[maxn],vis[maxn],tot,N,M; void dfs(int u) { if(vis[u]) return ; vis[u]=tot; dfs(a[u]); } void rebuild() { tot=0; rep(i,1,N) vis[i]=0; rep(i,1,N) if(!vis[i]) tot++,dfs(i); } int main() { scanf("%d",&N); rep(i,1,N) scanf("%d",&a[i]); rebuild(); scanf("%d",&M); if(M==N-tot) return puts("0"),0; int ans,opt=0; if(M>N-tot) ans=M-N+tot,opt=1; //合 else ans=N-tot-M;//拆 printf("%d\n",ans); rep(i,1,N) rep(j,1,N){ if(!ans) break; if(i!=j&&(abs(vis[i]-vis[j])?1:0)==opt) { swap(a[i],a[j]); ans--; printf("%d %d ",i,j); rebuild(); } } return 0; }
CodeForces - 441D: Valera and Swaps(置換群)