news 2026/4/23 9:36:29

算法竞赛备考冲刺必刷题(C++) | 洛谷 P5960 差分约束

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
算法竞赛备考冲刺必刷题(C++) | 洛谷 P5960 差分约束

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

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

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


【题目来源】

洛谷:P5960 【模板】差分约束 - 洛谷

【题目描述】

给出一组包含m mm个不等式,有n nn个未知数的形如:

{ x c 1 − x c 1 ′ ≤ y 1 x c 2 − x c 2 ′ ≤ y 2 ⋯ x c m − x c m ′ ≤ y m \begin{cases} x_{c_1}-x_{c'_1}\leq y_1 \\x_{c_2}-x_{c'_2} \leq y_2 \\ \cdots\\ x_{c_m} - x_{c'_m}\leq y_m\end{cases}xc1xc1y1xc2xc2y2xcmxcmym

的不等式组,求任意一组满足这个不等式组的解。

【输入】

第一行为两个正整数n , m n,mn,m,代表未知数的数量和不等式的数量。

接下来m mm行,每行包含三个整数c , c ′ , y c,c',yc,c,y,代表一个不等式x c − x c ′ ≤ y x_c-x_{c'}\leq yxcxcy

【输出】

一行,n nn个数,表示x 1 , x 2 ⋯ x n x_1 , x_2 \cdots x_nx1,x2xn的一组可行解,如果有多组解,请输出任意一组,无解请输出NO

【输入样例】

3 3 1 2 3 2 3 -2 1 3 1

【输出样例】

5 3 5

【算法标签】

《洛谷 P5960 差分约束》 #差分约束# #模板题# #Special Judge#

【代码详解】

#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong// 使用长整型constintN=5005,M=10005;// 最大顶点数和边数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(){queue<int>q;// SPFA队列// 初始化距离为无穷大memset(dist,0x3f,sizeof(dist));dist[0]=0;// 超级源点距离为0q.push(0);// 超级源点入队st[0]=true;// 标记在队列中while(!q.empty()){intt=q.front();// 取出队首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--){inta,b,c;cin>>a>>b>>c;// 注意:这里是 add(b, a, c),不是常见的 add(a, b, c)add(b,a,c);// 添加有向边 b→a,权重c}// 添加超级源点到所有顶点的边for(inti=1;i<=n;i++){add(0,i,0);// 0→i,权重0}// 执行SPFA,检测是否存在负环if(!spfa()){puts("NO");// 存在负环,无解}else{// 输出从超级源点到每个顶点的最短距离for(inti=1;i<=n;i++){cout<<dist[i]<<" ";}cout<<endl;}return0;}

【运行结果】

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