题意:给定一个无序序列。通过交换两个数使之有序。花费是每次交换的两个数的和。求最小花费。
我的第一道置换群题目嘞。啊哈。
比如下面这个序列:
先找出置换环。先给原序列从小到大排序。得到目标序列。
从目标序列开始,1的在原序列的下标是3,找到目标序列的第三个是3;3在原序列的下标是9,找到目标序列的第9个是9;9在原序列中的下标是4,找到目标序列的第4个是4;4在原序列的下标是1,找到目标序列的第1个是1。于是找到了一个置换环。
如何操作呢?
第一,可以拿置换中的每个元素和置换中的最小元素交换。
第二,先把置换中的最小元素和序列的最小元素交换,然后再重复一,然后再把它们交换回来。
取两种方法的花费的最小值累加即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
vector< pair<int,int> >a;
int main()
{
int n,x;
scanf("%d",&n);
for(int i=0;i<n;i++){
scanf("%d",&x);
a.push_back(make_pair(x,i));
}
sort(a.begin(),a.end());
int ans=0,m=a[0].first;
for(int i=0;i<n;i++){
if(a[i].second==-1) continue;
int j=a[i].second,w=a[i].first,k=1;
a[i].second=-1;
while(j!=i){
k++;
ans+=a[j].first;
int t=a[j].second;
a[j].second=-1;
j=t;
}
ans+=min((k-1)*w,(k-1)*m+2*(m+w));
}
printf("%d\n",ans);
return 0;
}