差分约束——Luogu1993 小K的农场

来源:互联网 发布:德尔塔高达淘宝 编辑:程序博客网 时间:2024/05/21 07:05

题面:传送门
第一题差分约束!
差分约束系统问题我们可以转化为建图求最短路等问题
像这题我们可以转化成求图中是否有负环
如果有的话那就不可行
然后建图时候的操作具体来看
如果是a-b>=c,那么就从a到b连一条长度为-c的边
如果是a-b<=c,那么就从b到a连一条长度为c的边
如果a=b那么连一条长度为0的双向边
具体如下:

    for(int i=1;i<=m;i++){        int j,x,y,z;scanf("%d",&j);        if(j==3){//a=b            scanf("%d%d",&x,&y);            addedge(x,y,0);addedge(y,x,0);        }else{            scanf("%d%d%d",&x,&y,&z);            if(j==1)addedge(x,y,-z);//a-b>=c            else addedge(y,x,z);//a-b<=c        }    }

最后求负环时用dfs的好
用bfs时间复杂度真的是非常。。。

#include<cstdio>#include<cstring>#include<cmath>#include<cstdlib>#include<algorithm>#include<iostream>#include<ctime>#include<queue>#include<stack>using namespace std;int dist[200001],n,m;int nedge=0,p[400001],c[400001],nex[400001],head[400001];bool vis[200001],flag=0;inline void addedge(int x,int y,int z){    p[++nedge]=y;c[nedge]=z;    nex[nedge]=head[x];head[x]=nedge;}void spfa(int x){    if(flag)return;    vis[x]=1;    for(int k=head[x];k;k=nex[k])if(dist[p[k]]>dist[x]+c[k]){        if(vis[p[k]])flag=1;        if(flag)break;        dist[p[k]]=dist[x]+c[k];        spfa(p[k]);    }    vis[x]=0;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)dist[i]=1e9;    for(int i=1;i<=m;i++){        int j,x,y,z;scanf("%d",&j);        if(j==3){            scanf("%d%d",&x,&y);            addedge(x,y,0);addedge(y,x,0);        }else{            scanf("%d%d%d",&x,&y,&z);            if(j==1)addedge(x,y,-z);            else addedge(y,x,z);        }    }    for(int i=1;i<=n;i++){        spfa(i);        if(flag)break;    }    if(flag)puts("No");    else puts("Yes");    return 0;}
1 0