【HDU 3270】Cow Sorting

来源:互联网 发布:中国国民收入数据库 编辑:程序博客网 时间:2024/04/30 09:37

这道题也是一道置换群的题,是黑书上的一道很经典的题

对于一个长度为k的轮换来说,可以证明最少需要交换k-1次才能使它回到本来的状态

如(1 2 3 4 5)需要至少交换四次,而可以每次用最小的数来交换

就可以得到最小的代价。但是还有一种情况就是

用轮换外的数放进来,然后交换k次之后再将此数放出去

就可以得到

ans=ans+min(sum+(k-1-1)*m,sum+k*Min+(m+Min))

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int SIZEN=100005;const int INF=1000005;struct elem{    int val;    int id;    bool operator <(const elem &a)const{        return val<a.val;    }};elem ss[SIZEN];int cow[SIZEN];int has[SIZEN];bool vis[SIZEN];int Min,k,sum,M;void dfs(int u){    if(vis[u]) return;    vis[u]=1;    sum+=cow[u];k++;    M=min(M,cow[u]);    dfs(has[u]);}void solve(int n){    Min=INF;    memset(vis,0,sizeof(vis));    for(int i=0;i<n;i++){        scanf("%d",&cow[i]);        ss[i].val=cow[i];        ss[i].id=i;        Min=min(Min,cow[i]);    }    sort(ss,ss+n);    for(int i=0;i<n;i++) has[ss[i].id]=i;    int ans=0;    for(int i=0;i<n;i++){        if(!vis[i]){            k=sum=0;            M=INF;            dfs(i);            ans+=sum+min((k-2)*M,M+(k+1)*Min);        }    }    printf("%d\n",ans);}int main(){    int n;    while(scanf("%d",&n)!=EOF) solve(n);}

0 0