牛客假日团队赛2 - H - 奶牛排序(置换群问题)

题目链接:https://ac.nowcoder.com/acm/contest/924/H

思路:涉及到群论的相关知识请自行百度,根据群论,置换可以分解为s个不相交循环的乘积,例如初始状态8 4 5 3 2 7,目标状态2 3 4 5 7 8,则可以分解为两个循环的乘积(8 2 7) ( 4 3 5)。对于任意一个循环 i ,设它的长度为 k ,循环内所有元素的和为sum, 为使交换的代价尽量小,我们让循环中最小的元素 m 参与所有的交换,其他元素只各参加一次,总花费为sum+m*(k-2)

例如刚才的栗子(8 2 7),其中2是其中最小的数。由于2占据了7的位置,所以2和7交换,得到序列8 4 5 3 7 2,这时2占据了8的位置,故2和8交换,得到序列2 4 5 3 7 8。此时循环里的各个数都到达了目标位置,称该循环已完成。

但是上述方法不一定最优,因为我们可以借助循环外的数来辅助交换,先让 m 和 n 个数中的最小值 mi 交换,让 mi 进入循环,并和剩下的 k - 1 个元素各交换一次把它们送入目标位置,最后再让 mi 和 m交换并退出循环,此时总花费为sum+mi+m*(k+1),它有可能比第一种方法更优,举个栗子:初始状态1 8 9 7 6,目标为 1 6 7 8 9,它可以分解为(1) (8 6 9 7),第一个循环只有一个元素,忽略;第二个循环如果按照第一种方法,花费为6+7+8+9+6*(4-2)=42,而第二种方法花费仅为6+7+8+9+6+1*(4+1)=41,第二种方法操作如下:

最优方案
操作数结果序列说明
1,66,8,9,7,1全局最小进入循环
1,96,8,1,7,91占据9的目标位置
1,76,8,7,1,91占据7的目标位置
1,86,1,7,8,91占据8的目标位置
1,61,6,7,8,91退出循环,6重新进入

综合两种方法,总花费为:cost = sum+\sum_{i=1}^{n}min(m*(k-2),m+mi*(k+1))

#include <bits/stdc++.h>
using namespace std;
#define debug(x) cerr<<#x<<'='<<(x)<<endl;
#define debug2(x, y) cerr<<"{"<<#x<<", "<<#y<<"} = {"<<(x)<<", "<<(y)<<"}"<<endl;
#define inf 0x3f3f3f3f
const int N = 1e5 + 7;
typedef long long ll;
int a[N], tmp[N], vis[N], pos[N], mi;
int main()
{
    int n; scanf("%d",&n);
    for(int i = 1; i <= n; i++)
        scanf("%d",&a[i]), tmp[i] = a[i];
    sort(a + 1, a + 1 + n); mi = a[1];
    for(int i = 1; i <= n; i++)
        pos[a[i]] = i;
    ll sum, ans = 0; int k = 0;
    for(int i = 1; i <= n; i++)
    {
        if(!vis[i])
        {
            int p = i, m = a[i];
            sum = 0, k = 0;
            while(!vis[p])
            {
                vis[p] = 1;
                k++;
                sum += a[p];
                m = min(m, a[p]);
                p = pos[tmp[p]];
            }
            ans += sum + min(m * (k - 2), m + mi * (k + 1));
        }
    }
    cout << ans << endl;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值