news 2026/3/11 22:45:30

算法竞赛备考冲刺必刷题(C++) | AcWing 1169 糖果

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法竞赛备考冲刺必刷题(C++) | AcWing 1169 糖果

本文分享的必刷题目是从蓝桥云课洛谷AcWing等知名刷题平台精心挑选而来,并结合各平台提供的算法标签和难度等级进行了系统分类。题目涵盖了从基础到进阶的多种算法和数据结构,旨在为不同阶段的编程学习者提供一条清晰、平稳的学习提升路径。

欢迎大家订阅我的专栏:算法题解:C++与Python实现!

附上汇总贴:算法竞赛备考冲刺必刷题(C++) | 汇总


【题目来源】

AcWing:1169. 糖果 - AcWing题库

【题目描述】

幼儿园里有N NN个小朋友,老师现在想要给这些小朋友们分配糖果,要求每个小朋友都要分到糖果。

但是小朋友们也有嫉妒心,总是会提出一些要求,比如小明不希望小红分到的糖果比他的多,于是在分配糖果的时候, 老师需要满足小朋友们的K KK个要求。

幼儿园的糖果总是有限的,老师想知道他至少需要准备多少个糖果,才能使得每个小朋友都能够分到糖果,并且满足小朋友们所有的要求。

【输入】

输入的第一行是两个整数N , K N,KN,K

接下来K KK行,表示分配糖果时需要满足的关系,每行3 33个数字X , A , B X,A,BX,A,B

  • 如果X = 1 X=1X=1.表示第A AA个小朋友分到的糖果必须和第B BB个小朋友分到的糖果一样多。
  • 如果X = 2 X=2X=2,表示第A AA个小朋友分到的糖果必须少于第B BB个小朋友分到的糖果。
  • 如果X = 3 X=3X=3,表示第A AA个小朋友分到的糖果必须不少于第B BB个小朋友分到的糖果。
  • 如果X = 4 X=4X=4,表示第A AA个小朋友分到的糖果必须多于第B BB个小朋友分到的糖果。
  • 如果X = 5 X=5X=5,表示第A AA个小朋友分到的糖果必须不多于第B BB个小朋友分到的糖果。

小朋友编号从1 11N NN

【输出】

输出一行,表示老师至少需要准备的糖果数,如果不能满足小朋友们的所有要求,就输出− 1 -11

【输入样例】

5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1

【输出样例】

11

【算法标签】

《AcWing 1169 糖果》 #图论# #Tarjan算法# #有向图的强连通分量# #SPFA# #差分约束#

【代码详解】

#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong// 使用长整型constintN=100005,M=N*3;// 最大顶点数和边数intn,m;// n: 顶点数, m: 约束数量inth[N],e[M],ne[M],w[M],idx;// 链式前向星存储图intq[N],dist[N];// 队列和距离数组intcnt[N],st[N];// 松弛计数和顶点是否在栈中/** * 添加有向边 * @param a 起点 * @param b 终点 * @param c 权重 */voidadd(inta,intb,intc){e[idx]=b;// 边指向的顶点w[idx]=c;// 边的权重ne[idx]=h[a];// 指向原链表头h[a]=idx++;// 更新头指针}/** * SPFA算法求最长路径,并检测正环 * 使用栈实现,适合检测正环 * @return 存在正环返回false,否则返回true */boolspfa(){stack<int>q;// 使用栈而不是队列,更易检测正环// 初始化距离为负无穷memset(dist,-0x3f,sizeof(dist));dist[0]=0;// 超级源点距离为0q.push(0);// 超级源点入栈st[0]=true;// 标记在栈中while(!q.empty()){intt=q.top();// 取出栈顶q.pop();st[t]=false;// 标记不在栈中// 遍历t的所有邻接边for(inti=h[t];i!=-1;i=ne[i]){intj=e[i];// 邻接顶点// 松弛操作:求最长路径if(dist[j]<dist[t]+w[i]){dist[j]=dist[t]+w[i];// 更新最长距离cnt[j]=cnt[t]+1;// 松弛次数+1// 如果顶点j被松弛了n+1次,说明存在正环if(cnt[j]>=n+1)// 注意是n+1,因为有超级源点{returnfalse;// 存在正环}// 如果j不在栈中,入栈if(!st[j]){q.push(j);st[j]=true;}}}}returntrue;// 不存在正环}signedmain()// 因为使用了#define int long long{// 输入顶点数和约束数量cin>>n>>m;// 初始化邻接表memset(h,-1,sizeof(h));// 处理m个约束while(m--){intx,a,b;cin>>x>>a>>b;// 根据约束类型添加边if(x==1)// a = b{add(b,a,0);// a ≥ badd(a,b,0);// b ≥ a}elseif(x==2)// a < b{add(a,b,1);// b ≥ a + 1}elseif(x==3)// a ≥ b{add(b,a,0);// a ≥ b}elseif(x==4)// a > b{add(b,a,1);// a ≥ b + 1}else// x == 5: b ≥ a{add(a,b,0);// b ≥ a}}// 添加超级源点到所有顶点的边for(inti=1;i<=n;i++){add(0,i,1);// 每个顶点至少分配1}// 执行SPFA,检测是否存在正环if(!spfa()){puts("-1");// 存在正环,无解}else{// 计算所有顶点的距离和intres=0;for(inti=1;i<=n;i++){res+=dist[i];}cout<<res<<endl;}return0;}

【运行结果】

5 7 1 1 2 2 3 2 4 4 1 3 4 5 5 4 5 2 3 5 4 5 1 11
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!