bzoj 1697: [Usaco2007 Feb]Cow Sorting牛排序
阿新 • • 發佈:2018-02-10
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牛排序