1697: [Usaco2007 Feb]Cow Sorting牛排序

1697: [Usaco2007 Feb]Cow Sorting牛排序

Time Limit: 5 Sec   Memory Limit: 64 MB
Submit: 485   Solved: 273
[ Submit][ Status][ Discuss]

Description

农夫JOHN准备把他的 N(1 <= N <= 10,000)头牛排队以便于行动。因为脾气大的牛有可能会捣乱,JOHN想把牛按脾气的大小排序。每一头牛的脾气都是一个在1到100,000之间的整数并且没有两头牛的脾气值相同。在排序过程中,JOHN 可以交换任意两头牛的位置。因为脾气大的牛不好移动,JOHN需要X+Y秒来交换脾气值为X和Y的两头牛。 请帮JOHN计算把所有牛排好序的最短时间。

Input

第1行: 一个数, N。

第2~N+1行: 每行一个数,第i+1行是第i头牛的脾气值。

Output

第1行: 一个数,把所有牛排好序的最短时间。

Sample Input

3
2
3
1

输入解释:

队列里有三头牛,脾气分别为 2,3, 1。

Sample Output

7

输出解释:
2 3 1 : 初始序列
2 1 3 : 交换脾气为3和1的牛(时间=1+3=4).
1 2 3 : 交换脾气为1和2的牛(时间=2+1=3).



具体是个叫做置换群的东西。。

每次找条置换环,ans += min(环上最小权值*(k-1),最小权值*(k-1)+2*(最小权值+环上最小权值))


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<vector>
#include<cstdlib>
#include<map>
#include<cmath>
using namespace std;

const int maxn = 1e4 + 10;

int now[maxn],ach[maxn],n,i,j,num[10*maxn];
bool vis[maxn];
long long ans = 0,Min = 1E9;

int main()
{
	#ifndef ONLINE_JUDGE
	#ifndef YZY
	  freopen(".in","r",stdin);
	  freopen(".out","w",stdout);
	#else
	  freopen("yzy.txt","r",stdin);
	#endif
	#endif

	cin >> n;
	for (i = 1; i <= n; i++) 
	{
		scanf("%d",&now[i]);
		ach[i] = now[i]; Min = min(1LL*now[i],Min);
		num[now[i]] = i;
	}
	sort (ach + 1,ach + n + 1);
	memset(vis,false,sizeof(vis));
	for (i = 1; i <= n; i++)
	  if (!vis[i])
	  {
	  	vis[i] = 1;
	  	int pos = num[ach[i]];
	  	long long MM = now[i],tot = now[i],k = 1;
	  	while (pos != i)
	  	{
	  		vis[pos] = 1;
	  		tot += 1LL*now[pos];
	  		MM = min(1LL*now[pos],MM);
	  		pos = num[ach[pos]];
	  		++k;
	  	}
	  	if (MM != Min) 
		  ans += min(tot + MM * (k-2),tot + Min * (k-1) + 2*(MM + Min) - MM);
		else ans += (tot + MM * (k-2));
	  }
	cout << ans;
	return 0;
}


你可能感兴趣的:(1697: [Usaco2007 Feb]Cow Sorting牛排序)