bzoj 1119: [POI2009]SLO(置换)
2016-05-21 08:57
381 查看
1119: [POI2009]SLO
Time Limit: 30 Sec Memory Limit: 162 MBSubmit: 557 Solved: 268
[Submit][Status][Discuss]
Description
对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和。请问将(ai)变为(bi)所需的最小代价是多少。Input
第一行N。第二行N个数表示wi。第三行N个数表示ai。第四行N个数表示bi。 2<=n<=1000000 100<=wi<=6500 1<=ai,bi<=n ai各不相等,bi各不相等 (ai)<>(bi) 样例中依次交换数字(2,5)(3,4)(1,5)Output
一个数,最小代价。Sample Input
62400 2000 1200 2400 1600 4000
1 4 5 3 6 2
5 3 2 4 6 1
Sample Output
11200HINT
感谢MT大牛贡献译文.Source
[Submit][Status][Discuss]
HOME Back
题解:置换。
这道题与poj 3270很相似,都牵扯到了轮换,对于一组轮换你总可以通过从中选取最小的数,用最小的数与其他数交换K-1次的方式使当前的轮换达到目标状态。
观察样例可以发现
1 4 5 3 6 2
5 3 2 4 6 1
样例中有三个轮换(5,2,1)(4,3)(6) 这里只的是数不是位置,当然如果改成位置的话就是(1,3,6)(2,4)
(5)。然后像poj 3270 那样搞就可以了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #define N 1000003 #define LL long long using namespace std; int n,m; LL w ,minn; int a ,cnt ,b ,use ; int main() { freopen("a.in","r",stdin); scanf("%d",&n); minn=1000000000; for (int i=1;i<=n;i++) scanf("%lld",&w[i]),minn=min(minn,w[i]); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=n;i++){ int x; scanf("%d",&x); cnt[x]=i; } LL ans=0; for (int i=1;i<=n;i++) if (!use[i]){ int j=i; LL mnow=1000000000; LL len=0; LL sum=0; while (!use[j]){ len++; mnow=min(mnow,w[a[j]]); sum+=w[a[j]]; use[j]=1; j=cnt[a[j]]; } if (len==1) continue; LL t1=sum+(LL)(len-2)*mnow; LL t2=sum+mnow+(LL)(len+1)*minn; ans+=min(t1,t2); } printf("%lld\n",ans); }
相关文章推荐
- 做个有前途的女子
- codevs1380 没有上司的舞会
- 这可能是史上最全的CSS自适应布局总结
- 输入框获得焦点时外边框颜色改变
- flask搭建个人博客(三)——后端视图函数
- 斗地主
- 洛谷 P1352 TYVJ P1052 CODEVS 1380 没有上司的舞会
- 拿到阿里,网易游戏,腾讯,smartx的offer的过程
- VS挂机移动鼠标代码
- 手心输入法
- Android正则
- NYOJ 心急的C小加
- comet技术
- java入门基础知识点总结
- durex-word
- GridView+下拉刷新+上拉加载
- 通过JSONP实现AJAX 跨域请求数据
- 无线网络密码破解
- BSG白山极客挑战赛——B君的圆锥(计算几何)
- [C++]using语义使用说明