小K的农场(差分约束)

题目大意 

n个点 m条描述 

  1. 农场 a 比农场 b 至少多种植了 c 个单位的作物。

  2. 农场 a 比农场 b 至多多种植了 c 个单位的作物。

  3. 农场 a 与农场 b 种植的作物数一样多。

题解

差分约束裸题 

可以把m条描述转换成一张图

ai-bi≥c--->bi-ai≤-c ai向bi连边权值为-c

ai-bi≤c    bi向ai连边 权值为c

ai-bi≥0并且ai-bi≤0所以ai和bi之间连双向边....

开始我不明白为什么要虚拟一个0点...原来图可能不连通....

判断负环...要用spfa的dfs判断 效率更高

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#define mmx 100003
using namespace std;

int n,m,a,b,c,od,flag,sumedge;
int dis[mmx],vis[mmx],head[mmx];

inline int read(){
    register char ch=getchar();register int x=0,f=1;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&& ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return f*x;
}

struct Edge{
    int x,y,z,nxt;
    Edge(int x=0,int y=0,int z=0,int nxt=0):
        x(x),y(y),z(z),nxt(nxt){}
}edge[mmx<<1];

inline void add(int x,int y,int z){
    edge[++sumedge]=Edge(x,y,z,head[x]);
    head[x]=sumedge;
}

inline void spfa(int now){
    vis[now]=1;
    for(int i=head[now];i;i=edge[i].nxt){
        int v=edge[i].y ;
        if(dis[v]>dis[now]+edge[i].z){
            dis[v]=dis[now]+edge[i].z;
            if(vis[v]){flag=1;return;}
            spfa(v);
        }
    }
    vis[now]=0;
}

int main(){
    n=read();m=read();
    for(register int i=1;i<=m;i++){
        od=read();a=read();b=read();
        if(od==1){c=read();add(a,b,-1*c);}
        if(od==2){c=read();add(b,a,c);}
        if(od==3){add(a,b,0);add(b,a,0);}
    }
    for(register int i=1;i<=n;i++)add(0,i,0);
    memset(dis,127/3,sizeof(dis));
    dis[0]=0;spfa(0);
    if(flag)printf("No\n");
    else printf("Yes\n");
    return 0;
}

 

posted @ 2017-08-18 11:11  ANhour  阅读(203)  评论(0编辑  收藏  举报