poj 2369 Permutations(置换群)

早起一水.
求原始序列到有序序列按照规则最少需要移动多少次.
分析下样例
1 2 3 4 5 

原始序列: 4 1 5 2 3

2 4 3 1 5
p(p(1))=p(4)=2;
p(p(2))=p(1)=4;
p(p(3))=p(5)=3;
...
...

1 2 5 4 3
p(p(p(1)))=p(2)=1;
p(p(p(2)))=p(4)=2;
p(p(p(3)))=p(3)=5;
...
...

4 1 3 2 5
p(p(p(p(1))))=p(1)=4;
p(p(p(p(2))))=p(2)=1;
p(p(p(p(3))))=p(5)=3;
2 4 5 1 3

1 2 3 4 5

就是两个循环节(1,2,4) 和(3,5) 我们只要求出lcm(循环节长度)便是其需要移动的次数

 
 

http://blog.csdn.net/kksleric/article/details/7793397这篇文章或许可以看看

.

/*
Problem ID: poj 2369
meaning: 求乱序到有序最少交换次数
Analyzing: 置换群
*/
#include <iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<vector>

using namespace std;
typedef struct even{int y1,y2,x;}even;

#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define LL long long
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)

#define maxn 1006

LL gcd(LL a,LL b) {return a?gcd(b%a,a):b;}
int main(){
    int N;
    int A[maxn],vis[maxn];
    scanf("%d",&N);
    FOR(i,0,N){
        scanf("%d",&A[i]);
        A[i]=A[i]-1;
    }
    LL res=1,len;
    memset(vis,0,sizeof(vis));
    FOR(i,0,N){
        if(!vis[i]){
            int j=i;
            len=0;
            while(!vis[j]){
                len++;
                vis[j]=1;
                j=A[j];
            }
        }
        res=res/gcd(res,len)*len;
    }
    printf("%d\n",res);
    return 0;
}




你可能感兴趣的:(struct,File,System)