Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 6364 | Accepted: 2462 |
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
Lines 2.. N+1: Each line contains a single integer: line i+1 describes the grumpiness of cow i.
Output
Sample Input
3 2 3 1
Sample Output
7
Hint
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).
(2) 借助于外界元素置换 -> 先让数列中最小元素Minn和群中最小元素sonMin交换,再用Minn与其它 t - 1个元素交换 t - 1 次,然后把Minn和sonMin交换回来
提醒: sum为当前群的数值之和。因此可以先统计所有元素之和,然后每次加上min(花费1, 花费2)即可;
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
#define MAX 10000+10
#define INF 1000000000+10
using namespace std;
struct record
{
int val, pos;//分别表示 数值和这个数有哪个位置的数置换得到的
}num[MAX];
bool cmp(record a, record b)
{
return a.val < b.val;//按照数值升序排列
}
int a[MAX];//n个数
int vis[MAX];//标记当前元素在不在某一个子群里面
int main()
{
int n, i, j;
LL ans;//最小 花费
int Minn;//记录数列里面最小值
int sonMin;//记录当前子群的最小值
int t;//记录子群元素个数
while(scanf("%d", &n) != EOF)
{
Minn = INF; ans = 0;
for(i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
ans += a[i];
num[i].val = a[i];
num[i].pos = i;
Minn = min(Minn, a[i]);//记录数列里面最小的值
}
sort(num+1, num+n+1, cmp);//升序排列
memset(vis, 0, sizeof(vis));//初始化
for(i = 1; i <= n; i++)
{
j = i;
if(!vis[j])//不存于 当前所有置换子群中
{
t = 0;
sonMin = a[j];
while(!vis[j])
{
vis[j] = 1;//标记
t++;//元素个数加一
sonMin = min(sonMin, a[j]);//更新子群最小值
j = num[j].pos;//->变换到它的上一位置
}
ans += min((t-2)*sonMin, (t+1)*Minn+sonMin);
}
}
printf("%lld\n", ans);
}
return 0;
}