zoukankan      html  css  js  c++  java
  • BZOJ_1119_[POI2009]SLO_置换+贪心

    BZOJ_1119_[POI2009]SLO_置换+贪心

    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

    6
    2400 2000 1200 2400 1600 4000
    1 4 5 3 6 2
    5 3 2 4 6 1

    Sample Output

    11200

    觉得这个想法挺好的我就又写了一遍。
    就是每个环拿出来,可能是里面最小的交换,也可能是全局最小的进去再出来。
     
    代码:
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    using namespace std;
    #define N 1000050
    typedef long long ll;
    inline char nc() {
        static char buf[100000],*p1,*p2;
        return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
    }
    int rd() {
        int x=0; char s=nc();
        while(s<'0'||s>'9') s=nc();
        while(s>='0'&&s<='9') x=(x<<1)+(x<<3)+s-'0',s=nc();
        return x;
    }
    int a[N],b[N],n,w[N],vis[N],mn=1<<30;
    int main() {
        n=rd();
        int i,x,j; ll ans=0;
        for(i=1;i<=n;i++) w[i]=rd(),mn=min(mn,w[i]);
        for(i=1;i<=n;i++) b[i]=rd();
        for(i=1;i<=n;i++) x=rd(),a[b[i]]=x;
        for(i=1;i<=n;i++) if(!vis[i]) {
            vis[i]=1;
            ll sum=w[i]; int mnn=w[i],siz=1;
            for(j=i;a[j]!=i;j=a[j],vis[j]=1,sum+=w[j],mnn=min(mnn,w[j]),siz++);
            ans+=min(ll(siz-2)*mnn+sum,ll(siz-1)*mn+sum-mnn+2*(mn+mnn));
        }
        printf("%lld
    ",ans);
    }
    
    
  • 相关阅读:
    redis问题排查
    javassist介绍
    Idea创建父子工程
    sentry的配置
    Redis的基本操作以及info命令
    es~日期类型需要注意的
    jboss~静态文件路由和自定义日志
    java~RMI引起的log4j漏洞
    链路跟踪~对接阿里ARMS
    navicat~导出数据库密码
  • 原文地址:https://www.cnblogs.com/suika/p/9426899.html
Copyright © 2011-2022 走看看