【学习笔记】差分约束

Page Views Count

概述#

差分约束系统,是由 n 个元素和 m 个约束条件构成的,其中每个约束条件形如 xixjyk

求解#

移项得到 xixj+yk,这样三角形不等式的形式类似最短路中的松弛,即由 jiyk 权值的边,最短路即满足约束条件。

这样便需要一个源点,原图不一定连通,因此建出超级源点 n+1,且规定 xi0,即 xixn+1+0,由 n+1i0 权值的边。

这样的负权图最短路可以使用 已死算法 SPFA 来求出。

点击查看代码
int n,m;
struct Graph{
    struct edge{
        int v,w;
        edge()=default;
        edge(int v_,int w_):v(v_),w(w_){}
    };
    vector<edge> E[maxn];
    inline void add_edge(int u,int v,int w){
        E[u].push_back(edge(v,w));
    }
    int dis[maxn],cnt[maxn];
    bool vis[maxn];
    inline void SPFA(){
        queue<int> q;
        memset(dis,0x3f,sizeof(dis));
        dis[n+1]=0,cnt[n+1]=0,vis[n+1]=1;
        q.push(n+1);
        while(!q.empty()){
            int u=q.front();
            vis[u]=0;
            q.pop();
            for(edge e:E[u]){
                int v=e.v,w=e.w;
                if(dis[u]+w<dis[v]){
                    dis[v]=dis[u]+w,cnt[v]=cnt[u]+1;
                    if(cnt[v]>=n) return printf("NO\n"),void();
                    if(!vis[v]){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
        }
        for(int i=1;i<=n;++i) printf("%d ",dis[i]);
        printf("\n");
    }
}G;

int main(){
    n=read(),m=read();
    for(int i=1;i<=n;++i) G.add_edge(n+1,i,0);
    for(int i=1;i<=m;++i){
        int u=read(),v=read(),w=read();
        G.add_edge(v,u,w);
    }
    G.SPFA();
    return 0;
}

对约束条件的调整#

一些简单的变形:

  • xixjkw(j,i)=k

  • xixjkxjxikw(i,j)=k

  • xi=xjxixj0xjxi0w(i,j)=w(j,i)=0

  • xixj<kxixjk1w(j,i)=k1

  • xixj>kxixjk+1w(i,j)=k1

对解的特殊限制#

事实上,当 (x1,x2,,xn) 为一组解时,(x1+k,x2+k,,xn+k) 同样为一组解。因此不等式组要么无解要么有无数组解,无解情况即为没有最短路也就是存在负环。

而在初始的设计中,xi0,当需要求出特定范围的解时,可以通过限定 disn+1 的初始值或 w(n+1,i) 的值来规定。假设将值修改为 c,则本质上是有 xic 的限定。

值得注意的是,最短路求出的结果一定是所有解中最大的。证明考虑最短路树,树边一定满足 xi=xj+w(j,i) 而一旦增加 xj 的值就会使答案不合法。

如果要求出满足 xik 的所有解中和最小的值,该如何处理?

首先可以通过变号得到 xi1,这一点可以对 disn+1 进行修改。这样所有的 x 值都已经取反,则 xi=xj+w(j,i) 变作 xj=xi+w(j,i),即 有向边方向改变,边权不变,此时最短路得到的最大解与要求最小解互为相反数。这本质上和求最长路时没有区别的。

例题#

Luogu-P3275 SCOI 2011 糖果#

建模比较容易,关键是 SPFA 被卡了。

发现边权只有 01,那么一个 SCC 中存在边权 1 即无解,这样每个 SCC 都一定相等,最短路用拓扑排序求出。

参考资料#

作者:SoyTony

出处:https://www.cnblogs.com/SoyTony/p/Learning_Notes_about_Difference_Constraints.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   SoyTony  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
more_horiz
keyboard_arrow_up light_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示