【luogu1993】 小K的农场 [差分约束]

1993 小K的农场

存一下 不想打字...

1、a-bgeq cabc,建边w[b,a]=c(表示abc

2、abc即bac,建边w[a,b]=-c(表示b比ac,注意不能建边w[b,a]=c因为这和第一个约束冲突,所以反过来就好了)

3、a==b时,建边w[a,b]=w[b,a]=0(表示ab相等)

然后从0向i=1~n每个点连边w[0,i]=0(随便值为多少,反正只是验证可行性)

最后跑spfa求最长路,出现环则输出No,否则输出Yes

对于多个不等式组:

v(x1) - v(x2) >= c1

v(x2) - v(x3) >= c2

……

把它们加起来就会得到:v(x1) - v(xn) >= c1 + c2 + …… + cn-1

实际上上面的不等式组恰好可以看成一条路径,每个不等式即路径上的一小段。(路径总长等于每段路径长度之和)

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) (x)<(y)?(y):(x)
#define Min(x,y) (x)<(y)?(x):(y)
#define ll long long
#define rg register
const int N= 10000+5,M=1000000+5,inf=0x3f3f3f3f,P=9999973;
int n,m,dis[N],flag=1;
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,w,nxt;}e[M<<1];
void add(int u,int v,int w){
    e[++tot]=(edge){v,w,head[u]},head[u]=tot;
}

bool in[N];
void dfs(int u){
    if(!flag) return;
    in[u]=1;
    for(int i=head[u],v;i;i=e[i].nxt){
        v=e[i].v;
        if(dis[v]<dis[u]+e[i].w){
            dis[v]=dis[u]+e[i].w;
            if(in[v]) {flag=0;return;}
            dfs(v);
        }
    }
    in[u]=0;
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    memset(dis,-inf,sizeof(dis));
    for(int i=1,op,u,v,w;i<=m;++i){
        rd(op),rd(u),rd(v);
        if(op==1) rd(w),add(v,u,w);
        else if(op==2) rd(w),add(u,v,-w);
        else add(u,v,0),add(v,u,0);
    }
    for(int i=1;i<=n;++i) add(0,i,0);
    dis[0]=0;
    dfs(0);
    if(flag) puts("Yes");
    else puts("No");
    return 0;
}
原文地址:https://www.cnblogs.com/lxyyyy/p/11211140.html