1. 程式人生 > >bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序

bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序

getc www. %d ref main geo source 置換 其他

題目鏈接

bzoj1697: [Usaco2007 Feb]Cow Sorting牛排序

題解

對於一對妞,每一次交換可以看做一個置換,初始序列看做輪換的乘
在一個輪換內,牛牛們是可以互相到達的
我們可以用輪換內代價最小的牛牛來交換其他的牛牛
花費為sum+min(len-1)-min
還有另一種方案可能更優,引入置換中的最小元素minn,與當前輪換中的最小值交換位置,花費minn+min,像上述一樣計算花費minn
(len-1)+(sum-min)
然後在換回去,總代價minn*(len+1)+sum+min
貪心一下就好惹

代碼

#include<cstdio>
#include<cstring>
#include<algorithm> using std::max; using std::min; inline int read() { int x=0;char c=getchar(); while(c<'0'||c>'9') c=getchar(); while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar(); return x; } const int maxn = 100007; bool vis[maxn]; int
tmp[maxn],to[maxn],next[maxn],ans=0; int main() { memset(vis,1,sizeof(vis)); int n=read(),maxx=-1,minn=0x7fffffff; for(int i=1;i<=n;++i) { to[i]=tmp[i]=read(); vis[tmp[i]]=false; maxx=max(to[i],maxx); minn=min(to[i],minn); } std::sort(to+1,to+n+1
); for(int i=1;i<=n;++i) { next[to[i]]=tmp[i]; } for(int i=1;i<=maxx;++i) { if(vis[next[i]])continue; vis[i]=1; int p=i,cnt=1,sum=i,tminn=i; while(next[p]!=i) { p=next[p];cnt++; sum+=p;vis[p]=1; tminn=min(tminn,p); } ans+=min(sum+(cnt-2)*tminn,sum+tminn+(cnt+1)*minn); } printf("%d\n",ans); return 0; }

bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序