POJ 3270 Cow Sorting
题意:
一个序列变为升序,操作为交换两个元素,代价为两元素之和,求最小代价
题解:
看了黑书...
首先循环因子分解
一个循环完成的最小代价要么是循环中最小元素依次与其他交换,要么引入全局最小值来交换
$sum+min(mn*(len-2),mn+Min*(len+1))$
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; const int N=1e4+5,M=1e5+5; inline int read(){ char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();} return x*f; } int n,a[N],c[M],Min=M,m; int f[N],ans; bool vis[N]; int main(){ //freopen("in","r",stdin); n=read(); for(int i=1;i<=n;i++) a[i]=read(),c[a[i]]++,Min=min(Min,a[i]),m=max(m,a[i]); for(int i=1;i<=m;i++) c[i]+=c[i-1]; for(int i=1;i<=n;i++) f[i]=c[a[i]]; for(int i=1;i<=n;i++) if(!vis[i]){ vis[i]=1; int u=f[i],sum=a[i],mn=a[i],len=1; while(u!=i) vis[u]=1,sum+=a[u],mn=min(mn,a[u]),len++,u=f[u]; ans+=sum+min(mn*(len-2),mn+Min*(len+1)); } printf("%d",ans); }