网络流之费用流

来源:互联网 发布:软件项目水果商场 编辑:程序博客网 时间:2024/06/14 04:33

求费用流目前好像只有EK+SPFA改版,时间复杂度为O(N*E*k),其中K为最大流值。但时间上的期望时间复杂度为:O(A*E*K),其中A为所有顶点进队列的平均次数,可以证明A一般小于等于2。


最小费用最大流:

#include <bits/stdc++.h>using namespace std;const int inf = 0x3f3f3f3f;const int maxn = 205;struct node{int v, to, w, cost, next;}edge[maxn*maxn];int no, n, m, s, t;int head[maxn], dis[maxn], vis[maxn], pre[maxn], rec[maxn];queue<int> q;inline void init(){no = 0;memset(head, -1, sizeof head);}inline void add(int u, int v, int w, int f){edge[no].v = v; edge[no].w = w; edge[no].cost = f;edge[no].next = head[u]; head[u] = no++;edge[no].v = u; edge[no].w = 0; edge[no].cost = -f;edge[no].next = head[v]; head[v] = no++;}int SPFA(int s, int t){memset(dis, 0x3f, sizeof dis);memset(vis, 0, sizeof vis);while(!q.empty()) q.pop();q.push(s); dis[s] = 0; vis[s] = 1;while(!q.empty()){int tp = q.front(); q.pop();vis[tp] = 0;int k = head[tp];while(k != -1){if(dis[edge[k].v] > dis[tp] + edge[k].cost && edge[k].w){dis[edge[k].v] = dis[tp] + edge[k].cost;pre[edge[k].v] = tp; rec[edge[k].v] = k;if(vis[edge[k].v] == 0){vis[edge[k].v] = 1;q.push(edge[k].v);}}k = edge[k].next;}}if(dis[t] == inf) return 0;return 1;}pair<int, int> Mcmf(int s, int t){int minflow, k, mincost = 0, maxflow = 0;while(SPFA(s, t)){k = t; minflow = inf;while(k != s){minflow = min(minflow, edge[rec[k]].w);k = pre[k];}k = t; maxflow += minflow;while(k != s){mincost += minflow*edge[rec[k]].cost;edge[rec[k]].w -= minflow;edge[rec[k]^1].w += minflow;k = pre[k];}}return make_pair(maxflow, mincost);}int main(){int u, v, w, f;scanf("%d %d %d %d", &n, &m, &s, &t);init();for(int i = 1; i <= m; ++i){scanf("%d %d %d %d", &u, &v, &w, &f);add(u, v, w, f);}pair<int, int> ans = Mcmf(s, t);cout << ans.first << " " << ans.second << endl;return 0;}

有时候也会遇到最大费用最大流,其实只要在建图时将所有费用取负,最后求的最小费用取负就是最大费用。


最小费用最大流是指满足源点流出的流量最大时,总费用最小的一个网络,模板都是基于此。

最大费用最大流则是将所有的费用取负,然后再跑一遍最小费用最大流,将最终的最小费用取负就是最大流量下的最大费用了。

最大费用可行流关注的是费用而非流量是否最大,那么当我们在寻找可改进路时如果从源点到汇点的dis变成大于0的时侯,则表明可改进路不会再减少费用了,所以在SPFA寻找增广路时return的条件改为dis[t] <= 0即可。

最小费用可行流没有意义。


继续加油~