孤独的小Z (差分约束)
差分约束:
- 一系列的不等式,看有没有满足条件的解
- 转化为文字就是 至少多,至多多, 等等字样 要反应过来
- 比如 a-b>=x, 然后这个可以变化为 b-a<=-x, 用大于还是小于看题目
- 然后 这个东西 和 图论联系在一起 a-b>=x 相当于 a>=x+b, x就是边权值,如果相等就 2个点相互连接 w=0;
- 至少>= 就是求最长路,(才能满足条件嘛)
- 至多<=, 就是求最短路
- 不存在解,就是有环. (局部正确是没有问题的)
- 利用spfa算法
本题就是模板题:

#include <bits/stdc++.h> using namespace std; #define ri register int #define M 200005 int n,m; struct dian{ int to,val; }; vector <dian> p[M]; int T; int dis[M]; int flag=0; int vis[M],cnt[M]; queue<int> q; void dfs(int a) { while(!q.empty()) q.pop(); q.push(a); while(!q.empty()) { a=q.front();q.pop(); vis[a]=0; for(ri i=0;i<p[a].size();i++) { int b=p[a][i].to; if(dis[b]<dis[a]+p[a][i].val) { dis[b]=dis[a]+p[a][i].val; cnt[b]=cnt[a]+1; if(cnt[b]>=n) { flag=1;break; } if(vis[b]==0) { q.push(b); vis[b]=1; } } } if(flag) break; } } int main(){ ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>T; while(T--) { cin>>n>>m; for(ri i=1;i<=n;i++) { p[i].clear(); dis[i]=0; } flag=0; for(ri i=1;i<=m;i++) { int a,b,c,d; cin>>a; if(a==1) { cin>>b>>c>>d; dian t; t.to=b;t.val=d; p[c].push_back(t); } if(a==2) { cin>>b>>c>>d; dian t; t.to=c;t.val=-d; p[b].push_back(t); } if(a==3) { cin>>b>>c; dian t; t.to=c;t.val=0; p[b].push_back(t); t.to=b;t.val=0; p[c].push_back(t); } } for(ri i=1;i<=n;i++) { vis[i]=0;cnt[i]=0; } for(ri i=1;i<=n;i++) { if(dis[i]==0) { dfs(i); } } if(flag) { cout<<-1<<endl; continue; } int ans=0; for(ri i=1;i<=n;i++) ans+=dis[i]; cout<<ans<<endl; } return 0; }