解题报告:P5960 【模板】差分约束算法(及常用技巧)
P5960 【模板】差分约束算法
差分约束系统
给出 n 个变量和 m 个约束条件,形如 xi−xj≤ckx_i - x_j \leq c_kxi−xj≤ck,你需要求出一组解,使得所有约束条件均被满足。
怎样解这个差分约束系统呢?我们将上面的不等式变形一下:xi≤xj+ckx_i \leq x_j + c_kxi≤xj+ck
容易发现这个形式和最短路中的三角形不等式 disv≤disu+wdis_v \leq dis_u + wdisv≤disu+w非常相似。
因此我们就将这个问题转化为一个求最短路的问题:比如对于上面这个不等式,我们从 j 向 i 连一条权值为 ckc_kck的边。接下来,我们再新建一个 0 号点,从 0 号点向其他所有点连一条权值为 0 的边。这个操作相当于新增了一个变量 x0x_0x0和 n 个约束条件:xi≤x0x_i \leq x_0xi≤x0,从而将所有变量都和 x0x_0x0这一个变量联系起来。
然后以 0 号点为起点,用 spfa 跑最短路。如果有负权环,差分约束系统无解。否则设从 0 号点到 i 号点的最短路为 disidis_idisi,则 xi=disix_i = dis_ixi=disi即为差分约束系统的一组可行解。
如上图,该图存在负环,如果一直沿着负环走,最短路径将会越来越小,最后到达−∞-∞−∞。
而此时的不等式就会出现矛盾,也就以为着没有正确的解
常用技巧
很多时候差分约束的条件并不是简单的小于等于号,这时候我们需要稍微做点变形。
如果有 xi−xj≥ckx_i - x_j \geq c_kxi−xj≥ck,则可以两边同时乘 −1,将不等号反转过来。
如果有 xi−xj=ckx_i - x_j = c_kxi−xj=ck,则可以把这个等式拆分为 xi−xj≤ckx_i - x_j \leq c_kxi−xj≤ck和 xi−xj≥ckx_i - x_j \geq c_kxi−xj≥ck两个约束条件,如果要求的是最值问题,那么我们应该统一符号,A=BA = BA=B改成A>=B,B>=AA>= B,B>= AA>=B,B>=A。
#include<map>
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstring>
#include<queue>
#include<vector>using namespace std;const int N = 5007;
const int M = 50007;
const int INF = 0x3f3f3f3f;
typedef pair<int,int> PII;int n,m;
int ver[M],edge[M],nex[M],head[N],tot;
int dis[N],vis[N],cnt[N];void add(int x,int y,int z){ver[++tot] = y;edge[tot] = z;nex[tot] = head[x];head[x] = tot;
}bool spfa(int s){queue<int>q;memset(vis,0,sizeof vis);memset(dis,0x3f,sizeof dis);dis[s] = 0;vis[s] = 1;q.push(s);while(q.size()){int x = q.front();q.pop();vis[x] = 0;for(int i = head[x];i;i = nex[i]){int y = ver[i],z = edge[i];if(dis[y] > dis[x] + z){dis[y] = dis[x] + z;cnt[y] = cnt[x] + 1;if(cnt[y] >= n)return false;if(!vis[y]){vis[y] = 1;q.push(y);}}}}return true;
}int main(){scanf("%d%d",&n,&m);for(int i = 1;i <= n;++i)//建超级源点add(0,i,0);for(int i = 1;i <= m;++i){int x,y,z;scanf("%d%d%d",&x,&y,&z);add(y,x,z);//xi - xj ≤ k//j来更新i,所以j向i连一条权值为k的边}if(!spfa(0))puts("NO");else {for(int i = 1;i <= n;++i)printf("%d ",dis[i]);puts("");}return 0;
}
解题报告:P5960 【模板】差分约束算法(及常用技巧)相关推荐
- 【模板】差分约束算法
[模板]差分约束算法 题意: 题解: 模板题 算法讲解 给出一组包含 m 个不等式,有 n 个未知数.求任意一组满足这个不等式组的解,或判定无解. 连边之后跑最短路,保证每个连通块都没有负环即可. 也 ...
- 【图论】差分约束算法详解
一.前言 在介绍差分约束之前,我们首先需要知道差分约束是用来解决什么问题的:差分约束是一个用来解决形如 X<=Y+c 的二元不等式组的可行解的一个算法.在高中数学中我们会学习如何使用线性规划的方 ...
- 洛谷OJ:P5960 【模板】差分约束算法
思路:差分约束模板题,注意使用SPFA来判断负环,也即无解的情况. #include<queue> #include<vector> #include<string> ...
- ACM模板——差分约束
a-b≤c a到b连一条c 最短路判负环,有负环就不行 转载于:https://www.cnblogs.com/Asurudo/p/11533296.html
- 算法题常用技巧C++
刷题常用技巧C++ 常用头文件 #include <iostream> #include <cstdio> #include <fstream> #include ...
- 【POJ - 1275】Cashier Employment(差分约束,建图)
题干: A supermarket in Tehran is open 24 hours a day every day and needs a number of cashiers to fit i ...
- 【HDU - 3440】House Man(差分约束)
题干: In Fuzhou, there is a crazy super man. He can't fly, but he could jump from housetop to housetop ...
- 2021字节跳动校招秋招算法面试真题解题报告--leetcode148 排序链表,内含7种语言答案
148.排序链表 1.题目描述 在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序 2.解题报告 针对nlogn的排序算法,主要有快速排序,归并排序和堆排序.其中,堆排序利用了数 ...
- poj1716(差分约束+SPFA)
题意:整数间隔[a,b],a<b,是以a开头和以b结尾的所有连续整数的集合.在包含至少两个不同整数的集合中找到每个间隔的最小元素数. 思路:采用差分约束算法:当问题可以转化为形如一组 xi‑x' ...
最新文章
- OUYA游戏开发快速入门教程第1章了解OUYA及其设备
- 云原生生态周报 Vol. 17 | Helm 3 发布首个 beta 版本
- php怎么上传函数,php上传函数怎么封装
- 多线程编程学习笔记——线程池(二)
- Linux的最大文件限制数ulimit
- Newton迭代法求无约束目标函数极小值matlab实现
- 【洛谷 P2764】 最小路径覆盖问题(最大流)
- c语言指针知识点小结,C语言指针知识点总结
- 《自己动手写网络爬虫》笔记2-Http状态码
- STM32MP157 Linux系统移植开发篇16:Linux内核音频驱动移植
- 电脑自带的edge浏览器无法访问解决问题
- 【LoRaWan】节点端(一)--SX1278介绍
- centos7图形界面和dos界面
- xml组合时间串解析
- 笔记本电脑C盘变红或变满,怎么处理?
- 抖音SEO优化源码,企业号搜索排名系统,矩阵分发。
- 深圳Java学习:Java中的原子操作
- HTML下拉框选择事件
- 《深入理解Windows操作系统》笔记4
- 什么时间段申购新股?新股申购的八大时机!确定时机能挽回三年损失!