1 条题解
-
0
这道题给了两个全排列 ,给了交换每个数的权值,求通过交换使 和 完全相同的最小总权值。 可以发现 和 中相同下标的数之间可以构成一个环。 而很容易想到环内的交换肯定是较优的。 由于每个数必然被交换一次,那么和它交换的数越小代价就越小。 所以对于环内的交换可以每次都用最小的数去换。 总代价为 。 接着还可以想到如果环内的数的权值都过大,这时可以使用环外的最小值来代替最小值进行交换。 总代价为 , 为整个权值数组的最小值。 这样对于每个环都计算一遍累计出总答案。 代码如下:
#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
- 上传者