[bzoj1119][POI2009]SLO

本文解析了 POI2009 中 SLO 问题的算法思路,通过群论思想确定轮换操作并计算将一个排列转换为另一个排列所需的最小代价。介绍了如何利用轮换中的最小值优化交换过程,并考虑特殊情况下的最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1119: [POI2009]SLO

Time Limit: 30 Sec Memory Limit: 162 MB
Submit: 747 Solved: 359
[Submit][Status][Discuss]
Description

对于一个1-N的排列(ai),每次你可以交换两个数ax与ay(x<>y),代价为W(ax)+W(ay) 若干次交换的代价为每次交换的代价之和。请问将(ai)变为(bi)所需的最小代价是多少。

Input

第一行N。第二行N个数表示wi。第三行N个数表示ai。第四行N个数表示bi。 2<=n<=1000000 100<=wi<=6500 1<=ai,bi<=n ai各不相等,bi各不相等 (ai)<>(bi) 样例中依次交换数字(2,5)(3,4)(1,5)

Output

一个数,最小代价。

Sample Input

6

2400 2000 1200 2400 1600 4000

1 4 5 3 6 2

5 3 2 4 6 1
Sample Output

11200
HINT

感谢MT大牛贡献译文.

Source

sol:
发现这道题显然是道群论题,那么一个数字需要到达的位置是确定的,可以确定出若干个轮换,对于一个轮换显然所有数至少会被交换一次,然后都用这个轮换中的最小的那个数换显然优。然而还有一种情况,比如这个轮换外的点都很优秀,那你可以把外面最小的点放进来,然后交换完再换回去。

#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1100000;
int pos,n,m,a[N],aim[N],Min[N],ID,val[N],size[N],low;
bool vis[N];
ll ans,Val[N];
inline int read()
{
    char c;
    int res,flag=0;
    while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
    res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
    return flag?-res:res;
}
int main()
{
//  freopen("1119.txt","r",stdin);
    n=read();
    low=1e9;
    for(int i=1;i<=n;++i)
    {
        val[i]=read();
        low=min(low,val[i]);
    }
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=n;++i) aim[read()]=i;
    for(int i=1;i<=n;++i) Min[i]=1e9;
    for(int i=1;i<=n;++i)
    if(!vis[i])
    {
        ++ID;
        pos=i;
        while(!vis[pos])
        {
            vis[pos]=1;
            Min[ID]=min(Min[ID],val[a[pos]]);
            Val[ID]+=val[a[pos]];
            size[ID]++;
            pos=aim[a[pos]]; 
        }
    }
    for(int i=1;i<=ID;++i)
    if(size[i]>1)
    ans+=min((ll)Min[i]*(size[i]-2)+Val[i],(ll)low*(size[i]+1)+Val[i]+Min[i]);
    cout<<ans;
}

1. 用户与身体信息管理模块 用户信息管理: 注册登录:支持手机号 / 邮箱注册,密码加密存储,提供第三方快捷登录(模拟) 个人资料:记录基本信息(姓名、年龄、性别、身高、体重、职业) 健康目标:用户设置目标(如 “减重 5kg”“增肌”“维持健康”)及期望周期 身体状态跟踪: 体重记录:定期录入体重数据,生成体重变化曲线(折线图) 身体指标:记录 BMI(自动计算)、体脂率(可选)、基础代谢率(根据身高体重估算) 健康状况:用户可填写特殊情况(如糖尿病、过敏食物、素食偏好),系统据此调整推荐 2. 膳食记录与食物数据库模块 食物数据库: 基础信息:包含常见食物(如米饭、鸡蛋、牛肉)的名称、类别(主食 / 肉类 / 蔬菜等)、每份重量 营养成分:记录每 100g 食物的热量(kcal)、蛋白质、脂肪、碳水化合物、维生素、矿物质含量 数据库维护:管理员可添加新食物、更新营养数据,支持按名称 / 类别检索 膳食记录功能: 快速记录:用户选择食物、输入食用量(克 / 份),系统自动计算摄入的营养成分 餐次分类:按早餐 / 午餐 / 晚餐 / 加餐分类记录,支持上传餐食照片(可选) 批量操作:提供常见套餐模板(如 “三明治 + 牛奶”),一键添加到记录 历史记录:按日期查看过往膳食记录,支持编辑 / 删除错误记录 3. 营养分析模块 每日营养摄入分析: 核心指标计算:统计当日摄入的总热量、蛋白质 / 脂肪 / 碳水化合物占比(按每日推荐量对比) 微量营养素分析:检查维生素(如维生素 C、钙、铁)的摄入是否达标 平衡评估:生成 “营养平衡度” 评分(0-100 分),指出摄入过剩或不足的营养素 趋势分析: 周 / 月营养趋势:用折线图展示近 7 天 / 30 天的热量、三大营养素摄入变化 对比分析:将实际摄入与推荐量对比(如 “蛋白质摄入仅达到推荐量的 70%”) 目标达成率:针对健
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值