题目大意:有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;
}