poj 3270
置换群~
所求即为每个循环群需用的最小值之和,即min(sum - curmin+curmin*(len-1),sum + curmin + Min*(len+1));
//============================================================================ // Name : 3270.cpp // Author : // Version : // Copyright : Your copyright notice // Description : Hello World in C++, Ansi-style //============================================================================ #include <iostream> #include <cstdio> #include <algorithm> #include <cstring> using namespace std; int a[10010], goal[10010], flag[10010], num[100010]; int curans, ans, Min, curmin, sum, len, t,com, n; int main() { freopen("a.txt", "r", stdin); while(scanf("%d", &n)!=EOF){ memset(a, 0, sizeof(a)); memset(flag, 0, sizeof(flag)); memset(goal, 0, sizeof(goal)); memset(num, 0, sizeof(num)); for(int i = 0;i < n;i++){ scanf("%d", &a[i]); goal[i] = a[i]; } sort(goal, goal+n); for(int i = 0;i < n;i++){ num[goal[i]] = i; } Min = goal[0]; ans = 0; for(int i = 0;i < n;i++){ if(flag[i] == 1) continue; flag[i] = 1; if(goal[i] == a[i]){ continue; } com = goal[i]; sum = goal[i]; t = a[i]; curmin = goal[i]; len = 1; while(t != com){ flag[num[t]] = 1; sum += t; len++; if(t < curmin){ curmin = t; } t = a[num[t]]; } curans = sum - curmin+curmin*(len-1); if(curans > sum + curmin + Min*(len+1)){ curans = sum + curmin + Min*(len+1); } ans += curans; } printf("%d\n", ans); } return 0; }