Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 5638 | Accepted: 2144 |
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).
Source
sum + (len - 2) * min。其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字。
其中,sum为这个循环所有数字的和,len为长度,min为这个环里面最小的数字,smallest是整个数列最小的数字。
//564K 547MS
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define inf 0x3f3f3f
#define M 10007
#define minn(a,b) a<b?a:b
using namespace std;
bool vis[M];
int first[M],last[M],minn,n,tot;//first为排序前的序列,last为排序后的序列,tot为环的个数,minn为整个序列的最小值
struct sa
{
int len;//环的长度
int minn;//环的最小值
}cir[M];
void dfs(int x)//寻找在同一个环中的元素
{
for(int i=0;i<n;i++)//在排序前的元素中找
if(!vis[i]&&x==first[i])//如果找到且没有访问过
{
vis[i]=true;
cir[tot].len++;
cir[tot].minn=min(cir[tot].minn,first[i]);
dfs(last[i]);
}
}
int main()
{
scanf("%d",&n);
minn=inf;tot=0;
memset(vis,false,sizeof(vis));
int ans=0;
for(int i=0;i<n;i++)
{
scanf("%d",&first[i]);
last[i]=first[i];
ans+=first[i];//ans为总的价值
minn=min(minn,first[i]);
}
sort(last,last+n);
for(int i=0;i<n;i++)
{
if(vis[i])continue;//如果访问过,就访问下一个
cir[tot].len=1;
cir[tot].minn=first[i];
vis[i]=true;
dfs(last[i]);
tot++;
}
for(int i=0;i<tot;i++)
ans+=minn(cir[i].minn*(cir[i].len-2),minn*(cir[i].len+1)+cir[i].minn);//去两种情况中的最小值
printf("%d\n",ans);
}