[关闭]
@11101001 2018-02-10T09:02:18.000000Z 字数 1045 阅读 958

bzoj1697: [Usaco2007 Feb]Cow Sorting牛排序


题目链接

bzoj1697: [Usaco2007 Feb]Cow Sorting牛排序

题解

对于一对妞,每一次交换可以看做一个置换,初始序列看做轮换的乘
在一个轮换内,牛牛们是可以互相到达的
我们可以用轮换内代价最小的牛牛来交换其他的牛牛
花费为sum+min*(len-1)-min
还有另一种方案可能更优,引入置换中的最小元素minn,与当前轮换中的最小值交换位置,花费minn+min,像上述一样计算花费minn*(len-1)+(sum-min)
然后在换回去,总代价minn*(len+1)+sum+min
贪心一下就好惹

代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. using std::max;
  5. using std::min;
  6. inline int read() {
  7. int x=0;char c=getchar();
  8. while(c<'0'||c>'9') c=getchar();
  9. while(c<='9'&&c>='0') x=x*10+c-'0',c=getchar();
  10. return x;
  11. }
  12. const int maxn = 100007;
  13. bool vis[maxn];
  14. int tmp[maxn],to[maxn],next[maxn],ans=0;
  15. int main() {
  16. memset(vis,1,sizeof(vis));
  17. int n=read(),maxx=-1,minn=0x7fffffff;
  18. for(int i=1;i<=n;++i) {
  19. to[i]=tmp[i]=read();
  20. vis[tmp[i]]=false;
  21. maxx=max(to[i],maxx);
  22. minn=min(to[i],minn);
  23. }
  24. std::sort(to+1,to+n+1);
  25. for(int i=1;i<=n;++i) {
  26. next[to[i]]=tmp[i];
  27. }
  28. for(int i=1;i<=maxx;++i) {
  29. if(vis[next[i]])continue;
  30. vis[i]=1;
  31. int p=i,cnt=1,sum=i,tminn=i;
  32. while(next[p]!=i) {
  33. p=next[p];cnt++;
  34. sum+=p;vis[p]=1;
  35. tminn=min(tminn,p);
  36. }
  37. ans+=min(sum+(cnt-2)*tminn,sum+tminn+(cnt+1)*minn);
  38. }
  39. printf("%d\n",ans);
  40. return 0;
  41. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注