码迷,mamicode.com
首页 > 其他好文 > 详细

poj3270--Cow Sorting(置换群)

时间:2015-07-24 22:42:10      阅读:148      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:点击打开链接

题目大意:给出你n个数,要求把这n个数排列成有序的(由小到大),每次可以交换两个数,花费是这两个数的和,现在求最小的花费

置换群的入门

求出每一个轮换的圈,对于每一个轮换中,只有在自身内交换就能完成有序,而不需要和其它轮换交叉。

一个轮换的最小值temp,轮换中有num个数,轮换的总和是sum,整个序列的最小值min1

让一个轮换花费最少有两种可能

1、轮换自身交换,轮换的最小值和其他值交换num-1次,那么花费是sum-temp+(num-1)*temp

2、用全局的最小值和轮换的最小值交换,然后执行轮换自身交换,然后再用全局最小值把轮换的最小值交换回来

sum-temp+(num-1)*min1+2*(min1+temp)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std ;
#define LL __int64
#define INF 0x3f3f3f3f
LL a[10010] , b[10010] , id[100010] ;
int vis[10010] ;
int main() {
    int n , i , j ;
    LL ans = 0 , min1 , num , sum , temp ;
    memset(vis,0,sizeof(vis)) ;
    scanf("%d", &n) ;
    for(i = 1 , min1 = INF ; i <= n ; i++) {
        scanf("%d", &a[i]) ;
        b[i] = a[i] ;
        id[ a[i] ] = i ;
        min1 = min(min1,a[i]) ;
    }
    sort(b+1,b+n+1) ;
    for(i = 1 ; i <= n ; i++) {
        if( vis[i] || a[i] == b[i] ) continue ;
        j = i ;
        sum = num = 0 ;
        temp = INF ;
        while( !vis[ id[ b[j] ] ] ) {
            j = id[ b[j] ] ;
            sum += a[j] ;
            num++ ;
            vis[ j ] = 1 ;
            temp = min(temp,a[j]) ;
        }
        ans += min( sum-temp+(num-1)*temp , sum-temp+(num-1)*min1+2*(min1+temp) ) ;
    }
    printf("%I64d\n", ans) ;
    return 0 ;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

poj3270--Cow Sorting(置换群)

标签:

原文地址:http://blog.csdn.net/winddreams/article/details/47046959

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!