链接:https://ac.nowcoder.com/acm/contest/554/I
来源:牛客网
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld
题目描述
坑坑作为一个ACMer,经常要对一组数字进行排序,在排序过程中,将两个数字交换位置的花销是这两个数字的和,慢慢的他想实现一种最低花销的排序方式,你们能帮助他吗?
输入描述:
输入包含多组测试数据。 每组测试输入包含一组数字包含的整数个数n以及n个整数mi(1<=n<1000,0<=mi<=10000)给定的整数互不重复。
输出描述:
对于每组测试数据,输出一个整数,给定整数按升序排序时所需花销的最小值。
示例1
输入
4 3 1 5 4
输出
13
将需要排序的数 原先的位置和末尾的位置用有向边连接
会发现其实其实就是一个个闭环
我们只需要将每个闭环都按照最低的权值处理
一共有两种方法
1.第一种就是有闭环中最小的数一次次替换
2.就是将闭环外最小的数与闭环内最小的数交换,再用闭环外最小的数对闭环内其他的数进行交换,最后将闭环内最小的数换回
保证权值最小的方法一定是二者之一
由此代码
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
int sum=0;
int cnt=0;
int a[1005];
int b[1005];
int pos[1005];
int vis[1005];
int Min;
void dfs(int x)
{
if(vis[x]==1) return ;
Min=min(Min,a[x]);
cnt++;
sum+=a[x];
vis[x]=1;
dfs(pos[x]);
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(vis,0,sizeof(vis));
int ans=0;
int MIN=1e9;
for(int i=1; i<=n; i++)
scanf("%d",&a[i]),b[i]=a[i],MIN=min(MIN,a[i]);
sort(b+1,b+1+n);
for(int i=1; i<=n; i++)
pos[i]=lower_bound(b+1,b+1+n,a[i])-b;
for(int i=1; i<=n; i++)
{
Min=1e9;
sum=0;
cnt=0;
if(vis[i]==0)
{
dfs(i);
//cout<<"{"<<sum<<" "<<cnt<<" "<<pos[i]<<" ";
int tmp=min(sum-Min+(cnt-1)*Min,sum+Min+(cnt+1)*MIN);
//cout<<i<<" "<<tmp<<"}"<<endl;
//int tmp=sum-Min+(cnt-1)*Min;
ans+=tmp;
}
}
printf("%d
",ans);
}
}