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;
}
}