上下界费用流
CodeForces 708D Incorrect Flow
这是道可行流最小费用的题目,这题好神奇。
看这老哥的题解就ok了。戳这
我觉得他少说了一条边,但代码中却体现了,就是一条流量为$(f,f)$的边,费用为0,就是固定流量的一条边。
还要注意一点是,$f>c$的时候,$f$往下调到$c$以下时,$c$是不动的。
#include <bits/stdc++.h> using namespace std; const int maxn = 200; const int INF = 1e9; int dist[maxn]; int pv[maxn],pe[maxn]; struct edge { int to, cap, pre; int cost; }e[1450]; int tot = 0, head[maxn]; void init(int n) { tot = 0; fill(head, head + n + 1, -1); } void add(int from,int to,int cap, int cost) { e[tot].pre = head[from]; e[tot].to = to; e[tot].cap = cap; e[tot].cost = cost; head[from] = tot++; } void addedge(int from,int to,int cap, int cost) { add(from,to,cap,cost); add(to,from,0,-cost); } int vis[maxn]; void SPFA(int s, int t) { for(int i = 1; i < maxn; i++) dist[i] = INF; memset(vis, 0, sizeof(vis)); dist[s] = 0, vis[s] = 1; queue<int> q; q.push(s); while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; ~i; i = e[i].pre) { int to = e[i].to, cap = e[i].cap; if(cap > 0 && (dist[to] - (dist[u] + e[i].cost)) > 0) { pv[to] = u, pe[to] = i; dist[to] = dist[u] + e[i].cost; if(!vis[to]) { vis[to] = 1; q.push(to); } } } } } int min_cost_flow(int s,int t,int f,int& max_flow) { int ret = 0; while(f>0) { SPFA(s, t); if(dist[t] == INF) return ret;///同一目的地,每次增广路都是最小费用 ///当所有边的流量都流净后,即没有残余网络,返回。 int d = f; for(int v=t;v!=s;v=pv[v]) { d = min(d, e[pe[v]].cap); } f -= d; max_flow += d; ret += (int)d*dist[t]; ///走一单位就消耗dist[t] for(int v=t;v!=s;v=pv[v]) { e[pe[v]].cap -= d; e[pe[v]^1].cap += d; } } return ret; } int d[maxn]; int main() { int n, m; scanf("%d %d", &n, &m); int u, v, c, f; init(n + 4); int ans = 0; for(int i = 1; i <= m; i++) { scanf("%d %d %d %d", &u, &v, &c, &f); d[u] -= f; d[v] += f; if(c >= f) { addedge(u, v, c - f, 1); addedge(u, v, INF, 2); addedge(v, u, f, 1); } else { ans += f - c; addedge(v, u, f - c, 0); addedge(u, v, INF, 2); addedge(v, u, c, 1);///c不用往下调啊啊啊 } } addedge(n, 1, INF, 0); int Ss = n + 1, Tt = n + 2; for(int i = 1; i <= n; i++) { if(d[i] > 0) addedge(Ss, i, d[i], 0); if(d[i] < 0) addedge(i, Tt, -d[i], 0); } int max_flow = 0; ans += min_cost_flow(Ss, Tt, INF, max_flow); printf("%d\n", ans); return 0; }