1 条题解

  • 0
    @ 2026-9-26 18:11:53

    这道题给了两个全排列 a,ba,b,给了交换每个数的权值,求通过交换使 aa 和 bb 完全相同的最小总权值。 可以发现 aa 和 bb 中相同下标的数之间可以构成一个环。 而很容易想到环内的交换肯定是较优的。 由于每个数必然被交换一次,那么和它交换的数越小代价就越小。 所以对于环内的交换可以每次都用最小的数去换。 总代价为 sum+mi×(len−2)sum+mi\times(len-2)。 接着还可以想到如果环内的数的权值都过大,这时可以使用环外的最小值来代替最小值进行交换。 总代价为 sum+mi+ami×(len+1)sum+mi+ami\times(len+1),amiami 为整个权值数组的最小值。 这样对于每个环都计算一遍累计出总答案。 代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,w[1000001],a[1000001],b[1000001],to[1000001],pos[1000001];
    bool vis[1000001];
    int ami=0x3f3f3f3f,ans;
    signed main(){
        ios::sync_with_stdio(0),cin.tie(0);
        cin>>n;
        for(int i=1;i<=n;i++)cin>>w[i],ami=min(ami,w[i]);
        for(int i=1;i<=n;i++)cin>>a[i];
        for(int i=1;i<=n;i++)cin>>b[i];
        for(int i=1;i<=n;i++)pos[b[i]]=i;
        for(int i=1;i<=n;i++)to[i]=pos[a[i]];
        for(int i=1;i<=n;i++){
            if(vis[i])continue;
            int j=i,k=0,sum=0,mi=0x3f3f3f3f;
            do{vis[j]=1,k++,sum+=w[a[j]],mi=min(mi,w[a[j]]),j=to[j];}while(j!=i);
            if(k==1)continue;
            int s1=sum+mi*(k-2),s2=sum+mi+ami*(k+1);
            ans+=min(s1,s2);
        }
        cout<<ans;
        return 0;
    }
    
    • 1

    信息

    ID
    2772
    时间
    3000ms
    内存
    64MiB
    难度
    8
    标签
    递交数
    14
    已通过
    8
    上传者