思考
首先题目是一道裸的差分约束,如果你还没有学过差分约束。那么我推荐你看看这篇博客,非常nice.
将不等式转化为图中的点和边,但是这里a=3的时候,要注意一下,即 要构造 a<=b b<=a 这种关系,那么就要从a向b连一条权值为0的边。
从b向a连一条权值为0的边。
之后 SPFA 判一下是否有负环就可以了。 (注意,请使用DFS,BFS稳稳TLE)
代码实现
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <cstdio> 2 #include <cstring> 3 const int MAXN=100050; 4 int head[MAXN],Count=0,n,m,x,y,z,flag=0,dis[MAXN]; 5 bool f[MAXN]; 6 struct node{ 7 //链式前向星存图,如果不懂。欢迎看我的另一个博客 8 int u,v,w,next; 9 node() {} 10 node(int _u,int _v,int _w,int _next){ 11 u = _u,v = _v, w = _w,next = _next; 12 } 13 }G[MAXN]; 14 15 void AddEdge(int u,int v,int w){ 16 G[Count] = node(u,v,w,head[u]); 17 head[u] = Count++; 18 } 19 void spfa(int x){ 20 f[x] = true; 21 for(int i=head[x];i!=-1;i=G[i].next){ 22 int v = G[i].v; 23 int w = G[i].w; 24 if(dis[v]>dis[i]+w){ 25 if(f[v]){ 26 flag = true; 27 return ; 28 } 29 dis[v] = dis[x] = w; 30 spfa(v); 31 } 32 } 33 f[x] = false; 34 return ; 35 } 36 37 int main(){ 38 memset(head,-1,sizeof(head)); 39 scanf("%d%d",&n,&m); 40 for(int i=1;i<=m;i++){ 41 scanf("%d",&x); 42 if(x==1){ 43 scanf("%d%d%d",&x,&y,&z); 44 AddEdge(x,y,0-z); 45 } 46 else if(x==2){ 47 scanf("%d%d%d",&x,&y,&z); 48 AddEdge(y,x,z); 49 } 50 else if(x==3){ 51 scanf("%d%d",&x,&y); 52 AddEdge(x,y,0); 53 AddEdge(y,x,0); 54 } 55 } 56 for(int i=0;i<Count;i++){ 57 dis[i] = 0; 58 spfa(i); 59 if(flag) break; 60 } 61 if(flag) printf("No"); 62 else printf("Yes"); 63 return 0; 64 }