小 K 的农场

小 K 在 Minecraft 里面建立很多很多的农场,总共 n 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共 m 个),以下列三种形式描述:
1.农场 a 比农场 b 至少多种植了 c 个单位的作物。
2.农场 a 比农场 b 至多多种植了 c 个单位的作物。
3.农场 a 与农场 b 种植的作物数一样多。
但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种植作物数量与他记忆中的所有信息吻合。

条件1:a>=b+c
条件2:a-b<=c
求不等式是否有解。
差分约束。对于形如a-b<=c的式子可以从b到a连一条边权为c的边,统一转化为这样的形式建图跑最短路。
或:对于形如a-b>=c的式子可以从b到a连一条边权为c的边,统一转化为这样的形式建图跑最长路。

判断解的可行性,有负权环则无解。dfs形式。

#include
using namespace std;

#define dd printf("Yes\n")
#define cc printf("No\n")

const int MAXN=3e5+5;

struct edge{
    int to,next,w;
}e[MAXN<<1];

int n,m;
int head[MAXN],dis[MAXN],cnt=1;
inline void add(int u,int v,int w){e[++cnt]=(edge){v,head[u],w},head[u]=cnt;}

int sta[MAXN],st=0;
bool insta[MAXN];
bool SPFA(int u){
    insta[u]=1;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].to,w=e[i].w;
        if(dis[u]+wif(!insta[v]){
                if(!SPFA(v))return 0;
            }
            else return 0;
        }
    }
    insta[u]=0;
    return 1;
}

void mem(){
    memset(insta,0,sizeof(insta));
    memset(dis,0x7f,sizeof(dis));
    dis[0]=0;
    for(int i=1;i<=n;i++)add(0,i,0);
}

int main(){ 
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        int tem1,tem2,tem3,tem4;
        scanf("%d%d%d",&tem1,&tem2,&tem3);
        if(tem1==1){
            scanf("%d",&tem4);
            add(tem2,tem3,-tem4);
        }
        else if(tem1==2){
            scanf("%d",&tem4);
            add(tem3,tem2,tem4);
        }
        else {
            add(tem2,tem3,0),add(tem3,tem2,0);
        }
    }
    mem();
    if(SPFA(0))dd;
    else cc;
    return 0;
}

你可能感兴趣的:(最短路)