1697: [Usaco2007 Feb]Cow Sorting牛排序
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 675 Solved: 392
[Submit][Status][Discuss]
Description
农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动。因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序。每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同。在排序过程中,JOHN 可以交换任意两头牛的位置。因为脾气大的牛不好移动,JOHN需要X+Y秒来交换脾气值为X和Y的两头牛。 请帮JOHN计算把所有牛排好序的最短时间。
Input
第1行: 一个数, N。
第2~N+1行: 每行一个数,第i+1行是第i头牛的脾气值。
Output
第1行: 一个数,把所有牛排好序的最短时间。
Sample Input
3
2
3
1
输入解释:
队列里有三头牛,脾气分别为 2,3, 1。
2
3
1
输入解释:
队列里有三头牛,脾气分别为 2,3, 1。
Sample Output
7
输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
1 2 3 : 交换脾气为1和2的牛(时间=2+1=3).
输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
1 2 3 : 交换脾气为1和2的牛(时间=2+1=3).
#include<cmath>
#include<ctime>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<complex>
#include<iostream>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<string>
#include<bitset>
#include<queue>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
const int N=100100;
const int M=1000100;
int n,ecnt,cnt,a[N],b[N],last[N];
ll f[N][2],mn[N];
bool book[N];
struct EDGE{int to,nt;}e[M];
inline void add(int u,int v)
{e[++ecnt]=(EDGE){v,last[u]};last[u]=ecnt;}
void seek(int u)
{
for(int i=last[u];i;i=e[i].nt)
{
if(book[e[i].to])continue;
book[e[i].to]=1;
mn[cnt]=min(int(mn[cnt]),e[i].to);
f[cnt][1]+=e[i].to;f[cnt][0]++;
seek(e[i].to);
}
}
void solve()
{
ll ans=0;
ll mnn=0X3f3f3f3f;
for(int i=1;i<=cnt;i++)mnn=min(mnn,mn[i]);
for(int i=1;i<=cnt;i++)
ans+=min(f[i][1]-mn[i]+(f[i][0]-1)*mn[i],f[i][1]+mn[i]+(f[i][0]+1)*mnn);
printf("%lld\n",ans);
}
int main()
{
n=read();memset(mn,0X3f,sizeof(mn));
for(int i=1;i<=n;i++)
{a[i]=read();b[i]=a[i];}
sort(b+1,b+1+n);
for(int i=1;i<=n;i++)
{add(a[i],b[i]);add(b[i],a[i]);}
for(int i=1;i<=n;i++)if(!book[a[i]])++cnt,seek(a[i]);
solve();
return 0;
}
/*
3
2
3
1
7
*/