题目连接:http://codeforces.com/contest/441/problem/D
CF的第四题一般是比较难的。即使他只是Div.2。
感觉这道题如果这是输入任意最小的且我在比赛时没读错题目应该是可以过的。
题意:对于一个数组p,p里的所有数据都有pi=i时,我们称他为XX数组。然后第一行先输入数组长度N,第二行输入N个数。第三行输入一个K。题目问的是,当前数组要经过几次变换(PI和PJ交换)后再最少经过K次交换后变成XX数组(即所有的pi=i),然后再输出如何变换的,变换的条件是I和J的字典序要最小。
思路:当时我没有考虑字典序的问题,于是如果有pi==j&&pj==i就交换。如果没有,再一个一个交换过来,每次的I和J存在一个结构体里再用结果体快排输出。当然如果字典序最小的话是另外的思路至今没有相同。
贴一个大神的代码:
#include <iostream>
using namespace std;
int p[3001], h[3001];
int main()
{
int n, m, i, j, k, hcnt, t, x;
cin>>n;
for (i=1; i<=n; i++)
cin>>p[i];
cin>>m;
for (hcnt=0,i=1; i<=n; i++)
{
if (h[i]==0)
{
h[i]=i;
for (j=p[i]; j!=i; j=p[j])
h[j]=i;
hcnt++;
}
}
if (n-hcnt==m)
cout<<0<<endl;
else if (n-hcnt>m)
{
i=n-hcnt-m;
cout<<i<<endl;
while (i--)
{
for (j=1; p[j]==j; j++);
for (k=j,x=p[j];p[k]!=j;k=p[k])
if (p[k]<x)
x=p[k];
cout<<j<<" "<<x<<" ";
t=p[j];
p[j]=p[x];
p[x]=t;
}
cout<<endl;
}
else
{
i = m+hcnt-n;
cout<<i<<endl;
while (i--)
{
for (j=1; j<=n; j++)
h[j]=0;
for (h[1]=1,j=p[1]; j!=1; j=p[j])
h[j]=1;
for (j=1; h[j]==1; j++);
cout<<"1 "<<j<<" ";
t=p[j];
p[j]=p[1];
p[1]=t;
}
cout<<endl;
}
return 0;
}