差分约束
求解差分约束系统,都可以转化为图论中单源最短路问题
对差分约束中的不等式 x i − x j ≤ c k x_i - x_j \le c_k xi−xj≤ck 可以移项成 x i ≤ c k + x j x_i \le c_k + x_j xi≤ck+xj
为什么差分约束可以与最短路联系?
比如有三个不等式
-
B − A ≤ c ( 1 ) B - A \le c(1) B−A≤c(1)
-
C − B ≤ a ( 2 ) C - B \le a(2) C−B≤a(2)
-
C − A ≤ b ( 3 ) C- A \le b(3) C−A≤b(3)
如果要求 C − A C-A C−A 的最大值,可知 max ( C − A ) = m i n ( b , a + c ) \max(C-A) = min(b, a+c) max(C−A)=min(b,a+c)
- 如果存在负环,则最短路无限小,最短路不存在
- 在不等式约束上表现为 x i − x 1 ≤ T x_i - x_1 \le T xi−x1≤T
- 得出的结论就是 x i x_i xi 的结果不存在
- 终点不可达
- 表明变量 x i x_i xi 与变量 1 之间没有约束关系
- x i x_i xi 的结果可以是无限大
不同不等式的转化
- 我们使用小于等于号,跑最短路,求得是一组最大解
- 使用大于等于号,跑最长路,可以求得一组最小解
- Dijkstra
- 如果图中存在负权边,不能求最短路
- 如果图中存在正权边,不能求最长路
- SPFA
- 初始化值改为负无穷
- 更新的大于号改成小于号
- Dijkstra
拓扑排序
给一个图中所有节点排序,图中的节点有一些前置节点
- 比如学完高数才能学机器学习,就给一条高数到机器学习的有向边
如果图中存在环路,就没法拓扑排序了。同时,可以用拓扑排序判断图中是否有环
拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点
Kahn算法
- 将入度为 0 的点组成一个集合 S S S
- 每次从 S S S 里面取一个节点 u u u 放入 L,然后遍历 u u u 的所有边 ( u , v ) (u,v) (u,v),并删除这个边。
- 如果 v v v 在移除这条边后入度为 0,则将其加入 S S S
- 最后 S S S 为空后,检查图中是否存在任何边。
- 若有,则图中有环路
- 否则返回 L,L中的顺序就是拓扑排序的结果
bool toposort(){
q = new queue();
for(int i = 0; i < n; i++)
if(in_deg[i] == 0) q.push(i);
ans = new vector();
while(!q.empty()){
u = q.pop();
ans.push_back(u);
for each edge(u, v)
if(--in_deg[v] == 0) q.push(v);
}
if(ans.size() == n){
for(int i = 0; i < n; i++)
cout << ans[i] << endl;
return true;
}
else return false;
}