题意:1-n的一个排列 p1, p2, ..., pn,f(p)的定义是此排列要交换最少的数对能够回到原排列1,2,3,4...n。给一个排列p。要将其变换成f值为m的排列,问至少要交换几个数对,并输出字典序最小的那组答案。

解法:处理出全部的置换群,求出环数k,此时f值为n-k。然后推断n-k和m的大小,分为两种操作

1、加环,这个是在随意元素个数大于1的环内交换随意两个数都能够做到加环

2、减环,交换随意两个环的随意两个元素。就能够做到将两个环连接起来

题目要求是输出字典序最小,那么就暴力搞。

代码:

/******************************************************
* author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std; #define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=3010;
const int INF=1000000007; vector<int> vec[Max];
int all=0;
int num[Max];
bool rem[Max];
int m;
int n;
int yinggai;
void make(int t)
{
if(rem[t])
return ;
rem[t]=1;
vec[all].push_back(t);
make(num[t]);
}
struct point
{
int p1,p2;
} points[Max];
bool operator<(point a,point b)
{
if(a.p1!=b.p1)
return a.p1<b.p1;
return a.p2<b.p2;
}
void solve()
{
all=0;
memset(rem,0,sizeof rem);
vec[0].clear();
for(int i=1; i<=n; i++)
{
if(!rem[i])
make(i),all++,vec[all].clear();
}
for(int i=0; i<all; i++)
sort(vec[i].begin(),vec[i].end());
}
int main()
{
scanf("%d",&n);
for(int i=1; i<=n; i++)
scanf("%d",num+i);
solve();
yinggai=n-all;
//cout<<" "<<yinggai<<endl;
scanf("%d",&m);
cout<<abs(yinggai-m)<<endl;
if(m>yinggai)
{
vector<int> help;
for(int i=0; i<all; i++)
{
if(vec[i][0]!=1)
help.push_back(vec[i][0]);
}
sort(help.begin(),help.end());
bool b=1;
printf("1 %d",help[0]);
for(int i=1; i<m-yinggai; i++)
printf(" 1 %d",help[i]);
cout<<endl;
}
else if(m<yinggai)
{
int t=yinggai-m;
//cout<<"fdas";
for(int i=0;i<t;i++)
{
solve();
pair<int,int > p(Max,Max);
for(int i=0;i<all;i++)
{
if(vec[i].size()>1&&vec[i][0]<p.first)
{
p.first=vec[i][0];
p.second=vec[i][1];
}
}
swap(num[p.first],num[p.second]);
if(i==0)
printf("%d %d",p.first,p.second);
else
printf(" %d %d",p.first,p.second);
}
}
return 0;
}

CF(441D Valera and Swaps)置换群的更多相关文章

  1. Codeforces 441D Valera and Swaps(置换群)

    题意: 给定一个1~n的排列(n<=3000),输出字典序最小且次数最少的交换操作,使得操作后的排列可以通过最少m次交换得到排列[1,2,...n] Solution: 可以将排列的对应关系看做 ...

  2. CodeForces - 441D: Valera and Swaps(置换群)

    A permutation p of length n is a sequence of distinct integers p1, p2, ..., pn (1 ≤ pi ≤ n). A permu ...

  3. CF 369C . Valera and Elections tree dfs 好题

    C. Valera and Elections   The city Valera lives in is going to hold elections to the city Parliament ...

  4. CF 441E Valera and Number

    CF 441E Description 一共执行\(k\)次,每次有\(p\%\)把\(x * 2\),有\((100 - p)\%\)把\(x + 1\).问二进制下\(x\)末尾期望\(0\)的个 ...

  5. Valera and Swaps

    题意: 定义 $f(p)$ 表示将 $p$ 序列变换为有序序列最少要交换多少次,给一 $1 \sim n$ 的排列 $a$ ,给一整数 $m$, 求问将 $a$ 最少交换多少次能得到 $p$ ,使得 ...

  6. cf E. Valera and Queries

    http://codeforces.com/contest/369/problem/E 题意:输入n,m; n 代表有多少个线段,m代表有多少个询问点集.每一个询问输出这些点的集合所占的线段的个数. ...

  7. cf D. Valera and Fools

    http://codeforces.com/contest/369/problem/D 标号最小的两个人会有四种状态:a活b活,a死b活,a活b死,a死b死:按照这四种状态dfs就可以求出最后的数量. ...

  8. cf C. Valera and Elections

    http://codeforces.com/contest/369/problem/C 先见边,然后dfs,在回溯的过程中,如果在这个点之后有多条有问题的边,就不选这个点,如果没有而且连接这个点的边还 ...

  9. cf B. Valera and Contest

    http://codeforces.com/contest/369/problem/B 先对k个处理,先处理sk%k个为sk/k+1,如果sk/k==0,k个数都为sk/k:对与剩下的数也按照同样的方 ...

随机推荐

  1. VBA清除Excelpassword保护,2003/2007/2010均适用

    Sub Macro1() ' ' Breaks worksheet and workbook structure passwords. Jason S ' probably originator of ...

  2. IOS中对图片进行重绘处理的方法总结

    一.CGImageRef是什么 CGImageRef是定义在QuartzCore框架中的一个结构体指针,用C语言编写.在CGImage.h文件中,我们可以看到下面的定义: ? 1 typedef st ...

  3. HDUJ 2074 叠筐 模拟

    叠筐 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submiss ...

  4. FileSystemWatcher使用方法具体解释

    FileSystemWatcher控件主要功能: 监控指定文件或文件夹的文件的创建.删除.修改.重命名等活动.能够动态地定义须要监控的文件类型及文件属性修改的类型. 1.经常使用的几个基本属性: (1 ...

  5. js判断是否是数字通用写法

    function isNumber(value){ var isNumber = value.match(/^(-?\d+)(\.\d+)?$/g) !=null; if(value.substrin ...

  6. jquery返回顶部

    // 返回顶部 var fixed_totop = $('.back_top').on('click',function(){ $('html, body').animate({scrollTop: ...

  7. Android Training: 设备管理

    Android 设备管理 Android2.2 通过Android设备管理API提供对企业级应用的支持.设备管理API在系统级别提供了设备管理特性.这些API可以在企业环境下,需要对员工设备进行控制时 ...

  8. C#中的委托和游戏中的运用

    C#中的委托与游戏中的运用 1.什么是委托 在C/C++中,有函数指针的概念,即指向函数的指针.当我们调用该指针时,就相当于调用了该指针所指向的函数,这就是函数指针的一个作用,而他另一个作用就是将自己 ...

  9. 三维偏序-二维LIS

    Another Longest Increasing Subsequence Problem 有两种思路. 思路一: 考虑到如果只有一维,那么可以用f[s]表示长度为s时,最后一个数是多少,把这个想法 ...

  10. OpenCV——Mat,IplImage,CvMat类型转换

    Mat,cvMat和IplImage这三种类型都可以代表和显示图像,三者区别如下 Mat类型侧重于计算,数学性较高,openCV对Mat类型的计算也进行了优化. 而CvMat和IplImage类型更侧 ...