poj 3270 Cow Sorting (置换群)

题意:

有n头牛,无序的排成一排,每个牛有一个权值w,现在要将牛按权值递增排序,每次可以交换两头牛的位置并且所需的代价是这两头牛的权值和,问使得牛权值按递增排序需要的最代价。

题解:

置换群的应用,每轮交换的最小代价要么就是指环内部取一个最小的作为踏板交换,要么就是在外部找一个最小的作为踏板交换,去两者的最小值。dfs出每个轮换,然后对每个轮换按上诉操作,最终累加得最优解。

#include<iostream>
#include<math.h>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#define B(x) (1<<(x))
using namespace std;
typedef long long ll;
void cmax(int& a,int b){ if(b>a)a=b; }
void cmin(int& a,int b){ if(b<a)a=b; }
void cmax(ll& a,ll b){ if(b>a)a=b; }
void cmin(ll& a,ll b){ if(b<a)a=b; }
void add(int& a,int b,int mod){ a=(a+b)%mod; }
void add(ll& a,ll b,ll mod){ a=(a+b)%mod; }
const int oo=0x3f3f3f3f;
const int MOD=2012;
const int maxn=11000;
int a[maxn],b[maxn];
int vis[maxn];
int n;
struct Node{
    int mi,cnt;
    void Init(){mi=oo;cnt=0;}
}z[maxn];
int tol;

void dfs(int u){
    for(int i=1;i<=n;i++){
        if(a[i]==u&&!vis[i]){
            vis[i]=1;
            cmin(z[tol].mi,a[i]);
            z[tol].cnt++;
            dfs(b[i]);
        }
    }
}

int main(){
    //freopen("E:\\read.txt","r",stdin);
    int Min,sum;
    while(scanf("%d",&n)!=EOF){
        Min=oo;
        sum=0;
        for(int i=1;i<=n;i++){
            scanf("%d",&b[i]);
            a[i]=b[i];
            cmin(Min,a[i]);
            sum+=a[i];
        }
        sort(b+1,b+1+n);
        memset(vis,0,sizeof vis);
        tol=0;
        for(int i=1;i<=n;i++){
            if(vis[i])continue;
            vis[i]=1;
            z[tol].Init();
            z[tol].cnt++;
            cmin(z[tol].mi,a[i]);
            dfs(b[i]);
            tol++;
        }
        for(int i=0;i<tol;i++){
            sum+=min(z[i].mi*(z[i].cnt-2),(z[i].cnt+1)*Min+z[i].mi);
        }
        printf("%d\n",sum);
    }
    return 0;
}










你可能感兴趣的:(poj 3270 Cow Sorting (置换群))