Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 7730 | Accepted: 3038 |
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).
题意:有n头牛,每头牛有不同的怒气值,交换两头牛的代价为两头牛怒气值的和,求把牛按怒气值降序排序所花费的最小代价和。
思路:一开始序列是乱序的,这些牛的序号和最终排好序的序号形成了一个置换,置换中有几个循环,而交换则是在每个循环自身中实现的,有两种情况:
1.本循环中最小怒气值的女和其他牛交换,直到本循环所有牛都排好序。
2.在全局中找到怒气值最小的牛,和本循环怒气值最小牛交换,进行1操作后再把两头牛交换回来。
比较这两种操作的代价,选择小者。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long ll;
struct Node
{
ll g;
int j;
}cow[10005],cow1[10005];
bool cmp(const Node a,const Node b)
{
return a.g<b.g;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
for(int i=0;i<10005;i++)
{
cow[i].g=cow[i].j=cow1[i].g=cow1[i].j=0;
}
for(int i=0;i<n;i++)
{
scanf("%lld",&cow[i].g);
cow[i].j=i;
cow1[i].g=cow[i].g;
}
sort(cow,cow+n,cmp);
for(int i=0;i<n;i++)
{
cow1[cow[i].j].j=i;
}
ll ans=0;
for(int i=0;i<n;i++)
{
if(cow1[i].j!=i)
{
int k=cow[i].j;
ll tmp1=0;
ll tmp2=2*(cow[0].g+cow[i].g);
while(cow1[i].j!=i)
{
int kk=cow[k].j; //交换的cow的最初位置
tmp1+=cow1[kk].g+cow1[k].g;
tmp2+=cow[0].g+cow1[kk].g;
swap(cow1[kk],cow1[k]);
k=kk;
}
ans+=min(tmp1,tmp2);
}
}
printf("%lld\n",ans);
}
}