题意: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. iOS获取一个方法的执行时间

    #import <Foundation/Foundation.h> #import <mach/mach_time.h> typedef void (^block)(void) ...

  2. (转)25个增强iOS应用程序性能的提示和技巧--中级篇

    在性能优化时,当你碰到一些复杂的问题,应该注意和使用如下技巧: 9.重用和延迟加载View10.缓存.缓存.缓存11.考虑绘制12.处理内存警告13.重用花销很大的对象14.使用Sprite Shee ...

  3. 2. QT窗体间值的传递

    一.主窗体与子窗体传参 方法有很多,这里介绍一种通过重载子窗体的构造函数实现主窗体参数传入到子窗体,并通过QT信号和槽的机制实现子窗口到主窗口值的传递. 主和子窗体的设置如下: 主要实现功能为: 1 ...

  4. 常用LINUX脚本汇总(1)

    1.查看磁盘使用空间 df -hl 2.查看文件或者文件夹大小 du -sh 文件(夹)名  查看文件大小  AIX系统为du -sg 3.查看当前用户下定时任务列表crontab -l 4.修改定时 ...

  5. [SQL学习笔记][用exists代替全称量词 ]

    学习sql的必经问题. 学生表student (id学号 Sname姓名 Sdept所在系) 课程表Course (crscode课程号 name课程名) 学生选课表transcript (studi ...

  6. MySql命令——函数

    1.拼接字段——Concata() 把多个串连接起来形成一个较长的串. select concat(value,'(',id,')') from test; 2.去掉空格 RTrim() 去掉右边的空 ...

  7. table-cell完成左侧定宽,右侧定宽及左右定宽等布局

    使用table-cell完成以下几种布局(ie8及以上兼容) 1.左侧定宽-右侧自适应 .left{ width: 300px; height: 500px; border: 1px solid; f ...

  8. js中退出语句break,continue和return 比较(转)

    原链接:http://blog.163.com/ued_er/blog/static/199703159201210283107315/ js中退出语句break,continue和return 比较 ...

  9. CSS属性值定义语法中的符号说名

    我们通常看到一个CSS语法,总是有很多符号在其中,这些符号是什么鬼呢,且看下面道来 这些符号可以大致分为2类:分组类与数量类. 1.分组类,就是分成一堆一堆啦: 符号 名称 描述 示例   并置 各部 ...

  10. 南阳oj-喷水装置(一)

    喷水装置(一) 时间限制:3000 ms  |  内存限制:65535 KB 难度:3   描述 现有一块草坪,长为20米,宽为2米,要在横中心线上放置半径为Ri的喷水装置,每个喷水装置的效果都会让以 ...