题意:1~n的一个排列,两两互换,每个位置每天只能做一次交换,问最多几天能交换成1~n,并且输出交换步骤。

解法:把该置换中所有的循环节找出,各循环节之间的交换是并行的,两两不相关,每天只需在循环节内部交换。

  若循环节长度为1,则无需交换,若循环节长度为2,则只需交换一次,若循环长度>2,则只需要交换2次。

  置换方法:每个循环节中的第一个和最后一个交换,第二个和倒数第二个交换...

  至于为什么只需两次,可以在纸上模拟一下置换过程,按上述置换方法一次交换后,一个循环节变成了(n-1)/2个长度为2的循环节,可以一次并行交换。

代码如下:

/*************************************************************************
> File Name: D.cpp
> Author: Chierush
> Mail: qinxiaojie1@gmail.com
> Created Time: 2013年07月24日 星期三 09时04分46秒
************************************************************************/ #include <iostream>
#include <cstring>
#include <cstdlib>
#include <set>
#include <cstdio>
#include <string>
#include <vector>
#include <map>
#include <cmath>
#include <algorithm> #define LL long long
#define LLU unsigned long long using namespace std; bool vis[5005];
int c[5005],n,a[5005],b[5005],_count;
vector<int>s[5005]; inline void swap(int &x,int &y)
{
x=x^y,y=x^y,x=x^y;
} void dfs(int x)
{
int y=a[x],Count=1;
while (y!=x)
{
++Count;
y=a[y];
}
c[x]=Count;
y=a[x];
while (y!=x)
{
vis[y]=true;
c[y]=Count;
y=a[y];
}
s[_count].clear();
if (Count>1)
{
s[_count].push_back(x);
y=a[x];
while (y!=x)
{
s[_count].push_back(y);
y=a[y];
}
++_count;
}
} int main()
{
scanf("%d",&n);
_count=0;
for (int i=1;i<=n;++i)
scanf("%d",&b[i]);
for (int i=1;i<=n;++i)
a[b[i]]=i;
for (int i=1;i<=n;++i)
if (!vis[i])
{
vis[i]=true;
dfs(i);
}
int ans=0;
for (int i=1;i<=n;++i)
if (c[i]>ans)
ans=c[i];
if (ans==1) ans=0;
else if (ans==2) ans=1;
else ans=2;
printf("%d\n",ans);
while (ans)
{
int z=0;
for (int i=0;i<_count;++i)
z+=s[i].size()/2;
printf("%d",z);
for (int i=0;i<_count;++i)
{
for (int j=0;j<s[i].size()/2;++j)
{
printf(" %d-%d",s[i][j],s[i][s[i].size()-j-1]);
swap(a[s[i][j]],a[s[i][s[i].size()-j-1]]);
}
}
printf("\n");
_count=0;
memset(vis,0,sizeof(vis[0])*(n+1));
memset(c,0,sizeof(c[0])*(n+1));
for (int i=1;i<=n;++i)
if (!vis[i])
{
vis[i]=true;
dfs(i);
}
ans=0;
for (int i=1;i<=n;++i)
if (c[i]>ans)
ans=c[i];
if (ans==1) ans=0;
else if (ans==2) ans=1;
else ans=2;
/*for (int i=1;i<=n;++i)
printf("%d ",a[i]);
printf("\n");*/
}
return 0;
}

  

SPOJ1421_Goods_循环节的更多相关文章

  1. UVA 10692 Huge Mods(指数循环节)

    指数循环节,由于a ^x = a ^(x % m + phi(m)) (mod m)仅在x >= phi(m)时成立,故应注意要判断 //by:Gavin http://www.cnblogs. ...

  2. 【POJ 2406】Power Strings(KMP循环节)

    终于靠着理解写出KMP了,两种KMP要代码中这种才能求循环节.i-next[i]就是循环节. #include<cstdio> #define N 1000005 char s[N]; i ...

  3. HNU 12869 Sequence(循环节)

    题目链接:http://acm.hnu.cn/online/?action=problem&type=show&id=12869 解题报告:看到n的范围这么大,一看就是找规律,把前30 ...

  4. Codeforces Round #383 (Div. 2) A,B,C,D 循环节,标记,暴力,并查集+分组背包

    A. Arpa’s hard exam and Mehrdad’s naive cheat time limit per test 1 second memory limit per test 256 ...

  5. 51Node 1035----最长的循环节

    51Node  1035----最长的循环节 正整数k的倒数1/k,写为10进制的小数如果为无限循环小数,则存在一个循环节,求<=n的数中,倒数循环节长度最长的那个数.     1/6= 0.1 ...

  6. POJ 2185 Milking Grid KMP(矩阵循环节)

                                                            Milking Grid Time Limit: 3000MS   Memory Lim ...

  7. KMP模板,最小循环节

    (可以转载,但请注明出处!) 下面是有关学习KMP的参考网站 http://blog.csdn.net/yaochunnian/article/details/7059486 http://blog. ...

  8. HDU 3746 Cyclic Nacklace 环形项链(KMP,循环节)

    题意: 给一个字符串,问:要补多少个字符才能让其出现循环?出现循环是指循环节与字符串长度不相等.比如abc要补多个变成abcabc.若已经循环,输出0. 思路: 根据最小循环节的公式,当len%(le ...

  9. UVA 10298 Power Strings 字符串的幂(KMP,最小循环节)

    题意: 定义a为一个字符串,a*a表示两个字符相连,即 an+1=a*an ,也就是出现循环了.给定一个字符串,若将其表示成an,问n最大为多少? 思路: 如果完全不循环,顶多就是类似于abc1这样, ...

随机推荐

  1. 超级简单的9patch

    转载请声明出处:http://blog.csdn.net/dawanganban 我们在有些应用中会用到将图片内部指定区域撑大的效果,如微信中的消息内容背景,这时候就要用到9patch图片,效果如下: ...

  2. 重装huson遇到的一些错误及解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 服务器换了一块新硬盘,拷贝回原来的数据后结果发现Apache tomcat服务不能启动了,错误提示是:本地计算机上的A ...

  3. Objective-C的基础数据结构

    类的数据结构 Class(指针) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 typedef struct objc_c ...

  4. 《用户体验要素》澄清了 UI 原型设计中看不见确感受得到的那一层

    <用户体验要素>澄清了看不见确感受得到的那一层 太阳火神的漂亮人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致&quo ...

  5. ASP.NET Core 项目配置 ( Startup ) - ASP.NET Core 基础教程 - 简单教程,简单编程

    原文:ASP.NET Core 项目配置 ( Startup ) - ASP.NET Core 基础教程 - 简单教程,简单编程 ASP.NET Core 项目配置 ( Startup ) 前面几章节 ...

  6. matlab进行离散点的曲线拟合

    原文:matlab进行离散点的曲线拟合 ployfit是matlab中基于最小二乘法的多项式拟合函数.最基础的用法如下: C=polyfit(X,Y,N) 其中: X : 需要拟合的点的横坐标 Y:需 ...

  7. ThreadPoolExecutor原理和使用

    大家先从ThreadPoolExecutor的整体流程入手: 针对ThreadPoolExecutor代码.我们来看下execute方法: public void execute(Runnable c ...

  8. style原则问题

    就近原则 1.“行内”覆盖“嵌入”,“嵌入”覆盖“外部”Style.xml <Window.Resources> <Grid.Resources> ….中间层 <Butt ...

  9. jquery ready和window onload区别

    window onload是指标签加载完成,并且标签资源加载完成: jquery ready是指标签加载完成,标签资源可能未加载完成 $(document).ready(function(){});= ...

  10. DOM解析xml实现读、写、增、删、改

    qt提供了三种方式解析xml,不过如果想实现对xml文件进行增.删.改等操作,还是DOM方式最方便. 项目配置 pro文件里面添加QT+=xml include <QtXml>,也可以in ...