差分约束学习笔记

给定 \(n\) 个形如 \(a-b≤c\) 的式子,求一组解或求两个变量间的最值

转化为图论问题跑最短/长路即可。

例:P3275 [SCOI2011]糖果

简化题意:给定一串约束条件,求所有元素的最小值。

稍微转换一下,就是使两个元素差值尽可能小。

例如 \(x_1+c≤x_2\) 如果用最短路去约束,则会取到最小值,所以应该用最长路去维护。

具体原因我也解释不来屮。

又因为题意对每个元素都有大于等于1的约束,所以从超级源点向每个元素的边边权要设为1。

这题就做完了,但是有些些小细节。

#include<bits/stdc++.h>
#define N 200005
#define int long long
using namespace std;
 
inline int read(){
    int x=0,w=1;
    char ch=getchar();
    while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return w*x;
}

int n,k,cnt,ans;
int dis[N],head[N],tot[N];
bool vis[N];
struct node{int to,next,w;}edge[N<<1];

void add(int u,int v,int w){
    edge[++cnt]=(node){v,head[u],w};
    head[u]=cnt;
}
void spfa(){
    stack<int> q;
    q.push(0);
    vis[0]=1;
    while(!q.empty()){
        int u=q.top();q.pop();vis[u]=0;
        for(int i=head[u];i;i=edge[i].next){
            int v=edge[i].to;
            if(dis[u]+edge[i].w>dis[v]){
                dis[v]=dis[u]+edge[i].w;
                if(!vis[v]){
                    vis[v]=1;tot[v]++;
                    if(tot[v]>=n) {puts("-1");exit(0);}
                    q.push(v);
                }
            }
        }
    }
}
signed main(){
    n=read();k=read();
    for(int i=1;i<=k;++i){
        int x=read(),a=read(),b=read();
        if(x==1) add(a,b,0),add(b,a,0);
        else if(x==2) {
            if(a==b){puts("-1");return 0;}
            add(a,b,1);
        }
        else if(x==3) add(b,a,0);
        else if(x==4) {
            if(a==b){ puts("-1");return 0;}
            add(b,a,1);
        }
        else  add(a,b,0);
    }
    for(int i=1;i<=n;++i) add(0,i,1);
    spfa();
    for(int i=1;i<=n;++i)
        ans+=dis[i];
    printf("%lld",ans);
    return 0;
}

最小值同理。

我真不知道啥时跑最长啥时跑最短屮。

考场上随机应变

​ ——————water_tomato

upd. on 2022.7.15

好像又懂了,补充一下。

最大值

将约束条件转化为形如 \(dis_i\le dis_j+w\)

\(j\)\(i\) 连一条边权为 \(w\) 的边,跑最短路。

为什么要跑最短路呢,因为跑最短路在这种情况下是跑到上界的,\(dis_i\) 就是把上界跑满的结果。

这样建图跑最长路就寄了,答案是错误的。

最小值

将约束条件转化为形如 \(dis_i\ge dis_j+w\)

\(j\)\(i\) 连一条边权为 \(w\) 的边,跑最长路,也可以跑到上界。

我们令 \(dis_1=0\) ,则跑最长路跑出来的 \(dis_3=4\) ,刚好卡到上界。

跑最短路跑出来的 \(dis_3=2\) ,不满足 1 , 4 之间的关系。

上面的最大值同理。

参考资料

https://blog.csdn.net/thexue/article/details/123587112

posted @ 2024-12-17 22:48  lxg_swrz  阅读(19)  评论(0)    收藏  举报