POJ-3270 Cow Sorting 置换群
题目链接:http://poj.org/problem?id=3270
把数列循环分解,注意到长度为k的循环最少用k-1次置换,那么次循环的最优值就是用循环中的最小值去与每个置换,还要考虑此循环中的最优值可以由其它循环影响,影响的那个循环肯定还有数列中的最小值。
1 //STATUS:C++_AC_16MS_396KB 2 #include<stdio.h> 3 #include<stdlib.h> 4 #include<string.h> 5 #include<math.h> 6 #include<iostream> 7 #include<string> 8 #include<algorithm> 9 #include<vector> 10 #include<queue> 11 #include<stack> 12 #include<map> 13 using namespace std; 14 #define LL long long 15 #define pii pair<int,int> 16 #define Max(a,b) ((a)>(b)?(a):(b)) 17 #define Min(a,b) ((a)<(b)?(a):(b)) 18 #define mem(a,b) memset(a,b,sizeof(a)) 19 #define lson l,mid,rt<<1 20 #define rson mid+1,r,rt<<1|1 21 const int N=10010,INF=0x3f3f3f3f,MOD=60007,STA=1000010; 22 const LL LNF=0x3f3f3f3f3f3f3f3f; 23 const double DNF=100000000000; 24 25 int num[N],c[N],ma[N*10],vis[N],minu[N],cnt[N],s[N]; 26 int n; 27 28 int main() 29 { 30 // freopen("in.txt","r",stdin); 31 int i,j,u,ans,k,t,minc; 32 while(~scanf("%d",&n)) 33 { 34 ans=k=0; 35 minc=INF; 36 mem(vis,0); 37 for(i=1;i<=n;i++){ 38 scanf("%d",&num[i]); 39 c[i]=num[i]; 40 } 41 sort(c+1,c+n+1); 42 for(i=1;i<=n;i++) 43 ma[c[i]]=i; 44 45 for(i=1;i<=n;i++){ 46 if(!vis[i]){ 47 minu[k]=INF; 48 cnt[k]=s[k]=0; 49 u=i; 50 while(!vis[u]){ 51 vis[u]=1; 52 minu[k]=Min(minu[k],c[u]); 53 minc=Min(minc,c[u]); 54 s[k]+=c[u]; 55 cnt[k]++; 56 u=ma[num[u]]; 57 } 58 s[k]=s[k]+(cnt[k]-2)*minu[k]; 59 k++; 60 } 61 } 62 for(i=0;i<k;i++){ 63 ans+=Min(s[i],s[i]+2*(minu[i]+minc)-(cnt[i]-1)*(minu[i]-minc)); 64 } 65 66 printf("%d\n",ans); 67 } 68 return 0; 69 }