差分约束与拓扑排序

差分约束

求解差分约束系统,都可以转化为图论中单源最短路问题

对差分约束中的不等式 x i − x j ≤ c k x_i - x_j \le c_k xixjck 可以移项成 x i ≤ c k + x j x_i \le c_k + x_j xick+xj

在这里插入图片描述

为什么差分约束可以与最短路联系?

比如有三个不等式

  • B − A ≤ c ( 1 ) B - A \le c(1) BAc(1)

  • C − B ≤ a ( 2 ) C - B \le a(2) CBa(2)

  • C − A ≤ b ( 3 ) C- A \le b(3) CAb(3)
    在这里插入图片描述

如果要求 C − A C-A CA 的最大值,可知 max ⁡ ( C − A ) = m i n ( b , a + c ) \max(C-A) = min(b, a+c) max(CA)=min(b,a+c)

  • 如果存在负环,则最短路无限小,最短路不存在
    • 在不等式约束上表现为 x i − x 1 ≤ T x_i - x_1 \le T xix1T
    • 得出的结论就是 x i x_i xi 的结果不存在
  • 终点不可达
    • 表明变量 x i x_i xi 与变量 1 之间没有约束关系
    • x i x_i xi 的结果可以是无限大

不同不等式的转化

在这里插入图片描述

  • 我们使用小于等于号,跑最短路,求得是一组最大解
  • 使用大于等于号,跑最长路,可以求得一组最小解
    • Dijkstra
      • 如果图中存在负权边,不能求最短路
      • 如果图中存在正权边,不能求最长路
    • SPFA
      • 初始化值改为负无穷
      • 更新的大于号改成小于号

拓扑排序

给一个图中所有节点排序,图中的节点有一些前置节点

  • 比如学完高数才能学机器学习,就给一条高数到机器学习的有向边

如果图中存在环路,就没法拓扑排序了。同时,可以用拓扑排序判断图中是否有环

拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点

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;
}

猜你喜欢

转载自blog.csdn.net/qq_52852138/article/details/125150203