链接:http://poj.org/problem?id=3270
做这道题,是昨天的比赛被1003给虐爆了.
/* Problem ID: poj 3270 meaning: 给出一列数,要将其排列成升序序列所需的最少花费,ps:cost 是交换的两数之和. Analyzing:置换群.黑书p248.找到每个循环节的长度ki和它的最小元素ti cost=sum+sum(min(ki-2)*ti,ti+(ki+1)m) */ #include <iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<vector> using namespace std; typedef struct even{int y1,y2,x;}even; #define FOR(i,s,t) for(int i=(s); i<(t); i++) #define LL long long #define BUG puts("here!!!") #define STOP system("pause") #define file_r(x) freopen(x, "r", stdin) #define file_w(x) freopen(x, "w", stdout) #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define maxn 10005 #define maxm 100005 LL gcd(LL a,LL b) {return a?gcd(b%a,a):b;} int main(){ int N,m=maxm; int A[maxn],B[maxn],hash[maxm],vis[maxn]; scanf("%d",&N); int cost=0; FOR(i,0,N){ scanf("%d",&A[i]); B[i]=A[i]; m=min(m,A[i]); } sort(B,B+N); FOR(i,0,N) hash[B[i]]=i; memset(vis,0,sizeof(vis)); cost=0; FOR(i,0,N){ if(!vis[i]){ int ki=0,sum=0; int temp=A[i],j=i,ti=maxm; while(1){ vis[j]=1; ki++; ti=min(ti,temp); sum+=temp; j=hash[temp]; temp=A[j]; if(temp==A[i]) break; } cost+=sum+min((ki-2)*ti,ti+(ki+1)*m); } } printf("%d\n",cost); return 0; }