给你一些没有重复的数,你只能交换其中两个数字,但是你要付出的代价是这两个数字之和。问你如何交换使得这些数字递增且代价最小。
置换群的概念:这些数字将会形成几个循环体。
对于每个循环体
1、循环体内和 + 循环体内最小值 + 所有数内最小值 * (该循环体内数字个数 + 1)
2、循环体内和 + 循环体内最小值 * (该循环体内数字个数 - 1)
以上两种取最小值即可。
//#pragma comment(linker, "/STACK:61400000,61400000")
#include <set>
#include <map>
#include <list>
#include <stack>
#include <queue>
#include <cmath>
#include <cstdio>
#include <vector>
#include <string>
#include <iomanip>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define pi 3.1415926535897932385
#define LL64 __int64
#define LL long long
#define oo 2147483647
#define N 100050
#define M 100
int a[N];
int b[N];
int h[N];
bool p[N];
int main()
{
int n;
//freopen("data.in", "r", stdin);
//freopen("data.out", "w", stdout);
//int _case = 1;
//scanf("%d", &t);
//while (t--)
//for (int _case = 1; _case <= t; _case++)
while (~scanf("%d", &n))
{
memset(p, 0, sizeof(p));
for (int i = 0; i < n; i++)
{
scanf("%d", &a[i]);
b[i] = a[i];
h[a[i]] = i;
}
sort(b, b + n);
int a1 = b[0];
int sum = 0;
while (n)
{
int i = 0;
while (p[i]) i++;
p[i] = 1;
int num = 1;
int x = i;
int s1 = 0;
int s2 = 0;
while (1)
{
x = h[b[x]];
if (x == i) break;
num++;
p[x] = 1;
s1 += b[x];
}
n -= num;
s2 = s1;
s1 += b[i] * (num - 1);
s2 += b[i] * 2 + (num + 1) * a1;
sum += (s1 < s2 ? s1 : s2);
}
printf("%d\n", sum);
}
}