最小费用最大流板子,没有压行。利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多。教程略去。转载请随意。
#include <cstdio> #include <cstring> #include <algorithm> #include <functional> #include <queue> using namespace std; ; const int inf = 0x33333333; typedef pair<int, int> int2; struct edge { int to, rev, cap, cost; }; int n; vector<edge> G[maxn]; void add_edge(int u, int v, int cap, int cost) { G[u].push_back((edge){v, (int)G[v].size(), cap, cost}); G[v].push_back((edge){u, (, , -cost}); } int2 mcmf(int s, int t) { //init static int h[maxn]; //标号 , cost = ; //solve while(true) { //dijkstra init static int dist[maxn]; //距离 static int pv[maxn]; //上一个顶点 static int pe[maxn]; //上一条弧 memset(dist, 0x33, sizeof dist); dist[s] = ; priority_queue< int2, vector<int2>, greater<int2> > q; q.push(int2(, s)); //dijkstra while(!q.empty()) { int2 x = q.top(); q.pop(); int u = x.second; if(x.first != dist[u]) { continue; } if(u == t) { break; } ; i < (int)G[u].size(); ++i) { edge &e = G[u][i]; int newcost = e.cost + h[u] - h[e.to]; && dist[e.to] > dist[u] + newcost) { dist[e.to] = dist[u] + newcost; q.push(int2(dist[e.to], e.to)); pv[e.to] = u; pe[e.to] = i; } } } if(dist[t] == inf) { break; } //augment ; i < n; ++i) { h[i] = min(h[i] + dist[i], inf); } int newflow = inf; for(int x = t; x != s; x = pv[x]) { edge &e = G[pv[x]][pe[x]]; newflow = min(newflow, e.cap); } flow += newflow; cost += newflow * h[t]; for(int x = t; x != s; x = pv[x]) { edge &e = G[pv[x]][pe[x]]; e.cap -= newflow; G[x][e.rev].cap += newflow; } } return make_pair(flow, cost); } int main(void) { int m, source, sink; scanf("%d%d%d%d", &n, &m, &source, &sink), --source, --sink; ; i < m; ++i) { int u, v, cap, cost; scanf("%d%d%d%d", &u, &v, &cap, &cost), --u, --v; add_edge(u, v, cap, cost); } int2 ans = mcmf(source, sink); printf("%d %d\n", ans.first, ans.second); ; }