差分约束系统

真的已经很久没有写博客了。。博客还是挺有用的,让自己复习的时候随时能理解,比如去年的欧拉路径(

1.是什么

“如果一个系统由n个变量和m个约束条件组成,其中每个约束条件形如Xj-Xi<=bk(i,j∈[1,n],k∈[1,m]),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。”

2.怎么思考

比如有这样的不等式组:

x1-x2<=y1

x3-x2<=y2

x3-x1<=y3

我们可以转化成:

x1<=x2+y1

x3<=x2+y2

x3<=x1+y3

可以发现这个东西很像单源最短路里面松弛边的操作,所以我们可以把求不等式的解转化成用spfa求最短路(用spfa是因为有负权边)

而当该图里面有负环时,不等式组无解

3.大概流程

1.建图

 用链式前向星就可以,但要注意add函数里面参数的位置

 x1-x2<=y1——add(x2,x1,y1)//这个是因为x1<=x2+y1 x1为终点,x2为出发点,y为路的长度

 x1-x2>=y1——x2-x1<=-y1——add(x1,x2,-y1)

 x1>x2——x1-x2>0——x1-x2>=1——add(x1,x2,-1)[当解一定为整数时]

 x1<x2——x1-x2<0——x1-x2<=-1——add(x2,x1,-1)[当解一定为整数时]

 x1=x2——add(x1,x2,0)add(x2,x1,0)

2.因为根据不等式组建的图可能是不连通的,所以我们建立一个0号结点,当作跑最短路时的起点

 add(每个结点,0,0)

 add(0,每个结点,0)

3.跑spfa,记得判负环的时候>n+1,因为还有一个0号结点

4.代码

 

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
const long long N=1e6+10;
queue<int> q;
int n,m,a,b,c;
int dis[N],ver[N],book[N];
int tot=0,head[N],nxt[N],v[N],w[N];
void add(int x,int y,int z){
    tot++;
    v[tot]=y;
    w[tot]=z;
    nxt[tot]=head[x];
    head[x]=tot;
}
void spfa(int x){
    memset(dis,0x3f3f3f3f,sizeof(dis));
    dis[x]=0;
    ver[x]=1;
    book[x]++;
    q.push(x);
    while(!q.empty()){
        int h=q.front();
        q.pop();
        ver[h]=0;
        for(int i=head[h];i;i=nxt[i]){
            if(dis[v[i]]>dis[h]+w[i]){
                dis[v[i]]=dis[h]+w[i];
                book[v[i]]=book[h]+1;
                if(book[v[i]]>n+1){
                    printf("NO\n");
                    exit(0);
                }
                if(ver[v[i]]==0){
                    ver[v[i]]=1;
                    q.push(v[i]);
                }
            }
        }
    }
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&a,&b,&c);
        add(b,a,c);
    }
    for(int i=1;i<=n;i++){
        add(0,i,1);
    }
    spfa(0);
    for(int i=1;i<=n;i++){
        printf("%d ",dis[i]);
    }
    return 0;
}

 

欢迎指错共同进步

 

posted @ 2023-08-01 20:51  dgdger  阅读(10)  评论(0编辑  收藏  举报