[51nod1125]交换机器的最小代价
设每个数最终的位置是$p_i$, 每个数当前的位置是$i$, 由于数是独一无二的, 所以pi - i是一一映射的关系
然后我们让$i -> p_i$, 建立一个图
那么, 考虑一个环, 我们可以让最小的值沿着来边走一$n-1$步($n$是环的大小), 亦或是让最小值和全局最小值交换一下, 让全局最小值来代替他走一圈, 再把全局最小值交换回去
(感觉显然是对的)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb push_back
#define ln '\n'
const int N = 2e5+5;
const int mod = 998244353;
inline void inc(int &a, int b){
a+=b;
if(a>=mod) a-=mod;
}
inline void dec(int &a, int b){
a-=b;
if(a<0) a+=mod;
}
int n, p[N], f[N], mn[N], siz[N];
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
ll sum[N];
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
vector<int> b;
for(int i=1; i<=n; i++) cin >> p[i], b.pb(p[i]);
sort(b.begin(), b.end());
for(int i=1; i<=n; i++)
p[i] = lower_bound(b.begin(), b.end(), p[i])-b.begin() + 1;
for(int i=1; i<=n; i++)
f[i] = i, sum[i] = mn[i] = b[p[i]-1], siz[i] = 1;
for(int i=1; i<=n; i++){
int fx = find(i), fy = find(p[i]);
if(fx != fy){
f[fy] = fx;
sum[fx] += sum[fy];
mn[fx] = min(mn[fx], mn[fy]);
siz[fx] += siz[fy];
}
}
ll ans = 0;
for(int i=1; i<=n; i++)
if(f[i] == i){
ll tmp1 = sum[i] - mn[i] + 1ll * mn[i] * (siz[i]-1);
ll tmp2 = sum[i] - mn[i] + 1ll * b[0] * (siz[i]-1) + (b[0]+mn[i])*2;
//把1跟最小值换一下, 然后让1走一圈, 然后换回来
ans = ans + min(tmp1, tmp2);
}
cout << ans << ln;
}

浙公网安备 33010602011771号