题目大意:有n个数和一些条件。条件有三种。
1.$a-bgeq c$;2.$a-bleq c$;3.$a=b$。
问你能否使得这些数满足所有条件。
解题思路:差分约束系统。
对于$a-bleq c$这样的不等式,我们将b->a连一条边权为c的有向边。
对于$a=b$,我们在a、b间连一条边权为0的无向边。
最后建立一个节点0,从它向所有节点连一条边权为0的有向边,然后从0开始跑SPFA判负环即可。
如果最后跑出来有负环,则无解,否则一定有解。
对于第1种条件,可以把它转变为$b-aleq -c$,然后按上述方法建图即可。
判负环时用dfs好像会更快一点。
C++ Code:
#include<cstdio> #include<cctype> #include<cstring> #include<cstdlib> int n,m,head[10005],dis[10005]; bool vis[10005]; struct edge{ int to,dis,nxt; }e[1000005]; inline int readint(){ char c=getchar(); for(;!isdigit(c);c=getchar()); int d=0; for(;isdigit(c);c=getchar()) d=(d<<3)+(d<<1)+(c^'0'); return d; } void dfs(int now){ vis[now]=true; for(int i=head[now];i!=-1;i=e[i].nxt){ if(dis[e[i].to]>dis[now]+e[i].dis){ dis[e[i].to]=dis[now]+e[i].dis; if(vis[e[i].to]){ puts("No"); exit(0); } dfs(e[i].to); } } vis[now]=false; } int main(){ int cnt=0; memset(head,-1,sizeof head); n=readint(),m=readint(); for(;m--;){ int opt=readint(),a=readint(),b=readint(); if(opt==1){ int c=readint(); e[++cnt]=(edge){b,-c,head[a]}; head[a]=cnt; }else if(opt==2){ int c=readint(); e[++cnt]=(edge){a,c,head[b]}; head[b]=cnt; }else{ e[++cnt]=(edge){a,0,head[b]}; head[b]=cnt; e[++cnt]=(edge){b,0,head[a]}; head[a]=cnt; } } for(int i=1;i<=n;++i){ e[++cnt]=(edge){i,0,head[0]}; head[0]=cnt; } memset(vis,0,sizeof vis); memset(dis,0x3f,sizeof dis); dis[0]=0; dfs(0); puts("Yes"); return 0; }