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

浙公网安备 33010602011771号