差分约束系统
1.du=dv 2.du+1<=dv 3.du>=dv 4.du>=dv+1 5.du<=dv
事实上,这道题希望总和最小,于是我们由小于号的左边连向右边,边权为常数项,跑最长路就可以了。
①:对于差分不等式,a - b <= c ,建一条 b 到 a 的权值为 c 的边,求的是最短路,得到的是最大值
②:对于不等式 a - b >= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值
③:存在负环的话是无解
④:求不出最短路(dist[ ]没有得到更新)的话是任意解
这是差分约束的通常解法
#include<bits/stdc++.h> using namespace std; const int N = 100010; struct edge { int nxt, to, w; } e[N << 2]; int n, k, cnt = 1; int vis[N], d[N], head[N], cir[N]; void link(int u, int v, int w) { e[++cnt].nxt = head[u]; head[u] = cnt; e[cnt].to = v; e[cnt].w = w; } int main() { scanf("%d%d", &n, &k); for(int i = 1; i <= k; ++i) { int u, v, opt; scanf("%d%d%d", &opt, &u, &v); if(opt == 1) { link(u, v, 0); link(v, u, 0); } if(opt == 2) { if(u == v) { puts("-1"); return 0; } link(u, v, 1); } if(opt == 3) link(v, u, 0); if(opt == 4) { if(u == v) { puts("-1"); return 0; } link(v, u, 1); } if(opt == 5) link(u, v, 0); } queue<int> q; memset(d, 0x3f3f, sizeof(d)); for(int i = n; i; --i) link(0, i, 1); d[0] = 0; q.push(0); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i; i = e[i].nxt) if(d[e[i].to] > d[u] + e[i].w) { d[e[i].to] = d[u] + e[i].w; if(vis[e[i].to] == 0) { ++cir[e[i].to]; if(cir[e[i].to] == n) { puts("-1"); return 0; } vis[e[i].to] = 1; q.push(e[i].to); } } } long long ans = 0; for(int i = 1; i <= n; ++i) ans += d[i]; printf("%lld\n", ans); return 0; }