Cow Sorting(置换群)

时间:2021-01-07 11:19:04
Cow Sorting
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 6664   Accepted: 2602

Description

Farmer John's N (1 ≤ N ≤ 10,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cows are more likely to damage FJ's milking equipment, FJ would like to reorder the cows in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (not necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes FJ a total of X+Y units of time to exchange two cows whose grumpiness levels are X and Y.

Please help FJ calculate the minimal time required to reorder the cows.

Input

Line 1: A single integer: N.  Lines 2..N+1: Each line contains a single integer: line i+1 describes the grumpiness of cow i

Output

Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.

Sample Input

3
2
3
1

Sample Output

7

Hint

2 3 1 : Initial order.  2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4).  1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).
题解:要把一个数列通过交换变成一个递增的序列,交换的权值是两个元素的和;
通过这n个数组成的数列 我们可以得到若干个置换子群。
            比如 给定序列{
                                            3  1  7  10  6
                                            1  3  6   7  10
                                        }上面序列要变成下面序列。 我们可以得到2个置换子群(1 -> 3)( 6 -> 10 -> 7)。
接下来有两种方法变换序列:
 
(1)  在子群里面置换 -> 用最小的元素sonMin和其它 t - 1 元素交换 t - 1 次,就有花费1:sum + (t - 2) * sonMin;  (2)  借助于外界元素置换 -> 先让数列中最小元素Minn和群中最小元素sonMin交换,再用Minn与其它 t - 1个元素交换 t - 1 次,然后把Minn和sonMin交换回来
       有花费2: sum + sonMin + Minn * (t + 1)。 提醒: sum为当前群的数值之和。因此可以先统计所有元素之和,然后每次加上min(花费1, 花费2)即可;
 
对于每个置换群的求法,可以用结构体存储原数值以及原数值对应的位置,然后按数值升序排列就求出变换的位置。
 
序列{                                                                                   {
              数值 3  1  7  10  6         ------>                                    数值 1  3  6  7 10
              位置 1  2  3   4   5         ------>                                    位置   2  1  5  3  4
          }             
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
typedef long long LL;
const int MAXN=;
int vis[MAXN];
struct Node{
int pos,val;
bool operator < (const Node &b)const{
if(val!=b.val)return val<b.val;
else return pos<b.val;
}
};
Node dt[MAXN];
int main(){
int N;
while(~SI(N)){
LL sum=;
int min_all=INF,min_area;
for(int i=;i<=N;i++){
SI(dt[i].val);
dt[i].pos=i;
sum+=dt[i].val;
min_all=min(min_all,dt[i].val);
}
sort(dt+,dt+N+);
mem(vis,);
int num;
for(int i=;i<=N;i++){
if(!vis[i]){
num=;
min_area=dt[i].val;
int j=i;
while(!vis[j]){
vis[j]=;
num++;
//printf("%d ",dt[j].val);
min_area=min(min_area,dt[j].val);
j=dt[j].pos;
}//puts("");
sum+=min((num-)*min_area,*(min_all+min_area)+(num-)*min_all-min_area);
}
}
printf("%lld\n",sum);
}
return ;
}