http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1125&judgeId=501829

这道题是以前数学专题做过类似的,就是学 置换 的时候
比如 2 3 4 1,就是一个循环,因为第一个位置是2,然后去找第二个位置,是3,又找第三个位置,是4,又找第四个位置,又回到了1。
而4 3 2 1,第一个位置是4,找第4个位置,是1,找第一个位置,又是4,所以{1,4}是个循环,同理{3,2}也是个循环

那我们为什么要找循环喃?
因为如果是一个有n个数的循环的话,那肯定要换n-1次才能换好,并且每次用最小的去换,最小的会用n-1次,其他的个用一次,这样花费才最小

而最小的这个数,可能是循环内部自己的人,也阔能是另外一个循环的,所以比较一哈,用哪个最小就行了~φ(>ω<*)

#include"iostream"
#include"algorithm"
using namespace std;
const int maxn=5e4+5;
int Rank[maxn];
int Sa[maxn];
long long a[maxn];
struct AAA
{
    long long v;
    int id;
};
AAA b[maxn];
bool cmp(AAA a,AAA b)
{
    return a.v<b.v;
}
bool vis[maxn];
int N;
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    while(cin>>N)
    {
        long long res=0;
        long long MIN=1e9+5,Min;
        for(int i=1;i<=N;i++)
        {
            vis[i]=0;
            cin>>b[i].v;
            b[i].id=i;
            a[i]=b[i].v;
            MIN=min(MIN,a[i]);
        }
        sort(b+1,b+1+N,cmp);
        for(int i=1;i<=N;i++)Sa[i]=b[i].id;
        for(int i=1;i<=N;i++)Rank[Sa[i]]=i;
        for(int i=1;i<=N;i++)
        {
            if(vis[i])continue;
            if(Sa[i]==i)continue;
            long long sum=0;
            Min=1e9+5;
            int t=i;
            long long cnt=0;
            while(vis[t]==0)
            {

                vis[t]=1;
                cnt++;
                Min=min(Min,a[t]);
                sum+=a[t];
                t=Sa[t];
            }
            long long res1=sum+(cnt-2)*Min;
            long long res2=sum+(cnt-1)*MIN-Min+2*(MIN+Min);
            res+=min(res1,res2);
        }
        cout<<res<<endl;
    }
}