当前位置: 首页 > news >正文

【例4-13】奖金(信息学奥赛一本通- P1352)

【题目描述】

由于无敌的凡凡在2005年世界英俊帅气男总决选中胜出,Yali Company总经理Mr.Z心情好,决定给每位员工发奖金。公司决定以每个人本年在公司的贡献为标准来计算他们得到奖金的多少。

于是Mr.Z下令召开m方会谈。每位参加会谈的代表提出了自己的意见:“我认为员工a的奖金应该比b高!”Mr.Z决定要找出一种奖金方案,满足各位代表的意见,且同时使得总奖金数最少。每位员工奖金最少为100元。

【输入】

第一行两个整数n,m,表示员工总数和代表数;

以下m行,每行2个整数a,b,表示某个代表认为第a号员工奖金应该比第b号员工高。

【输出】

若无法找到合理方案,则输出“Poor Xed”;否则输出一个数表示最少总奖金。

【输入样例】

2 1 1 2

【输出样例】

201

【提示】

【数据规模】

80%的数据满足:n≤1000,m≤2000;

100%的数据满足:n≤10000,m≤20000。

1. 题目背景与分析

核心问题:

公司给员工发奖金,存在M条建议,每条建议形式为:“员工A的奖金必须比B高”。要求满足所有建议,且总奖金数最少。基础奖金为 100 元。

模型转化:

这是一个典型的 “依赖关系” 问题。

如果“A的奖金 >B的奖金”,说明B是A的基础(或者说前驱)。只有确定了B的奖金,才能确定A的奖金。

  • 建图方向:建立一条从B指向A的有向边 (B->A)。

  • 图的性质:这是一个有向无环图。如果存在环(例如 A>B, B>A),则无法满足条件,输出 "Poor Xed"。

  • 目标:在满足拓扑序的前提下,求每个节点的最长路径长度(即层级)。


2. 算法选择:Kahn算法+动态规划

为了让总奖金最少,我们采取贪心策略:每个人只拿“刚好满足条件”的最低工资。

即:w[A]=max(所有前驱的工资) + 1。

为什么选择Kahn算法(入度表法)?

  1. 天然契合:Kahn 算法的核心是不断剥离“入度为0”的点。在本题中,入度为0 代表“没有比他工资更低的人了”,这些人直接拿基础工资 100 元。

  2. 层级递推:随着入度为0的点被移除,它们的后继节点的入度减少。当后继节点入度变为 0 时,说明它的所有下属工资都算好了,此时就可以结算它的工资。

  3. 判环简便:算法结束后,如果还有节点的入度不为0,说明存在环,直接判断无解。


3. 数据结构:邻接表(链式前向星)

由于题目数据范围是N<=10000, M<=20000,属于稀疏图。为了时间和空间效率,本题代码使用了邻接表(链式前向星)来存储图。

相比vector,链式前向星在空间上更紧凑,常数更小。

  • h[u]:存储节点u的第一条边的索引。

  • vtex[i]:第i条边指向的节点。

  • nxt[i]:第i条边的下一条同起点边的索引。


4. 完整代码

//Kahn 时间复杂度:O(N+M) 空间复杂度:O(N+M) #include <iostream> #include <queue> using namespace std; int n,m; int h[10010];//邻接表头指针数组 int vtex[20010];//邻接表第i条边终点的下标 int nxt[20010];//与邻接表第i条边同起点的下一条边的索引 int idx; int din[10010];//记录每个点的入度 int w[10010];//记录第i个员工的奖金 long long sum;//记录总奖金 queue<int> q; void addedge(int a,int b){ vtex[idx]=b; nxt[idx]=h[a]; h[a]=idx++; } int main(){ cin>>n>>m; //初始化邻接表头指针数组为-1 for(int i=1;i<=n;i++) h[i]=-1; //邻接表存边 因为本题点数过多,且为稀疏图 不选邻接矩阵 for(int i=1;i<=m;i++){ int a,b; cin>>a>>b; //第a号员工奖金应该比第b号员工高,就建立一条b->a的边 addedge(b,a); din[a]++;//a入度加一 } for(int i=1;i<=n;i++){//遍历所有员工 if(din[i]==0){//如果入度为0 q.push(i);//就入队 //初始化入度为0的员工,奖金100,因为他们不比任何员工奖金高 w[i]=100; } } while(!q.empty()){ int tmp=q.front();//访问队首元素 q.pop();//队首出队 //接下来访问邻接表找到所有与tmp有边相连的员工 int p=h[tmp]; while(p!=-1){ //a为应比tmp奖金高的员工编号 int a=vtex[p]; //更新a员工的奖金 w[a]=max(w[a],w[tmp]+1); //a员工入度-1 din[a]--; //如果a员工入度为0 就入队 if(din[a]==0) q.push(a); //更新指针 p=nxt[p]; } } //结束后,遍历所有员工,如果存在入度不为0的员工 //代表无法找到合理方案 for(int i=1;i<=n;i++){ if(din[i]!=0){ cout<<"Poor Xed"; return 0; } sum+=w[i];//总奖金 } //否则就输出总奖金 cout<<sum; return 0; }

5. 解题总结

  1. 建图方向

    • 一定要理清谁依赖谁。本题中“A比B高”意味着 A 依赖 B,所以边是B->A。如果建反了,求出来的就是最小值而不是最大值,逻辑会崩盘。

  2. 判环

    • 题目中可能存在矛盾的建议(如 A>B 且 B>A)。Kahn 算法天然支持判环:只要算法结束后还有点没进过队列(即din[i]!=0),就是有环。

  3. 数据类型

    • 虽然每个人奖金可能不多,但总奖金sum可能会超过int范围,使用long long是良好的编程习惯。

  4. 初始化

    • 链式前向星的h数组记得初始化为-1

    • 入度为0的点,初始奖金设为100。

这道题是拓扑排序的经典入门题,理解了它,就理解了“依赖关系解析”的核心逻辑。

http://www.jsqmd.com/news/267468/

相关文章:

  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的水果质量识别系统(Python+PySide6界面+训练代码)
  • python基于人工智能的智能客服系统设计与实现
  • 芯片制造企业网页如何集成百度开源上传组件实现分片上传源码?
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的活体人脸检测系统(Python+PySide6界面+训练代码)
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的铁轨缺陷检测系统(Python+PySide6界面+训练代码)
  • 基于Django的智慧农业农产品销售及农机设备管理系统设计与实现
  • 航空航天网页项目怎么用vue3实现大文件分片上传源码?
  • 基于python框架的房产交易服务平台的设计与实现
  • 互联网教育平台如何优化百度编辑器的Word公式渲染速度?
  • 基于python的婚庆公司服务平台的设计与实现
  • Edge TTS深度解析:跨平台文本转语音技术实践与性能优化
  • 汽车电子研发如何通过百度富文本编辑器处理CAD图纸注释?
  • 融合无人机与轨道交通的智能系统:面向巡检、客流、应急与物流的场景实现研究
  • 汽车制造企业网页如何实现大附件分片上传的源码?
  • 5分钟搞定DOL汉化美化:新手零基础配置指南
  • RedisInsight完整安装教程:在Windows上一键部署可视化Redis管理平台
  • 如何让 AI 跨行业接项目,全自动化帮你干活
  • 2026 年 1 月油桶烘箱厂家推荐排行榜,高温油桶烘箱,工业油桶烘箱,油桶烘箱加热原理,高效节能烘烤设备公司推荐! - 企业推荐官【官方】
  • LLM提示工程让遗传咨询更精准
  • OBS Spout2插件终极指南:实现跨应用4K视频无缝传输
  • STM32单片机智能储物柜快递柜无线APP快递员169(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 机械制造行业网页如何用html5实现大文件分片上传源码?
  • STM32单片机智能喂食器164
  • 金融终端如何通过百度ueditor实现跨浏览器截屏功能?
  • 基于51/STM32单片机自动售货机扫码支付无人超市缺货补货语音设计(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 东方博宜OJ 2053:图的 bfs 遍历 ← bfs + 链式前向星 / 邻接矩阵
  • 医院电子病历系统如何集成百度UE的PDF签名导入功能?
  • 2026 年 1 月蒸汽防爆烘箱厂家推荐排行榜,大型/高温/苏州地区蒸汽防爆烘箱,参数解析与价格指南,专业防爆与高效烘干实力之选 - 企业推荐官【官方】
  • 基于STM32单片机智能搬运机器人4维机械臂TFT彩屏摇杆设计套件132(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_文章底部可以扫码
  • 【日记】突破了风车,然后跟朝哥聊了很久的天(2810 字)