小K的农场(差分约束)
题目大意
n个点 m条描述
-
农场 a 比农场 b 至少多种植了 c 个单位的作物。
-
农场 a 比农场 b 至多多种植了 c 个单位的作物。
- 农场 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; }