最小费用最大流(luogu P3381 模板最小费用最大流)
Posted Q1143316492
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最小费用最大流(luogu P3381 模板最小费用最大流)相关的知识,希望对你有一定的参考价值。
题目描述
如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。
输入输出格式
输入格式:
第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。
接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。
输出格式:
一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。
输入输出样例
费用流模板:
在最大流的前提下,费用最小。由EK算法扩展。EK每次用bfs增广,把bfs改成spfa找到一条花费最小的路径即可,然后拿这条路去优化答案。
不会EK的先去拿EK写道最大流,不会spfa的拿spfa写道最短路径在往下看。
然后建边的时候反向弧的费用为正向弧的相反数,走反向弧相当于不走这一段边,那么最短路径部分当然要消除这一段的影响。
AC代码
1 #include <bits/stdc++.h> 2 3 4 using namespace std; 5 const int MAXN = 5010; 6 const int MAXM = 50010; 7 const int INF = 0x7FFFFFFF; 8 9 int n, m, first[MAXN], s, t, sign; 10 11 int max_flow, min_cost; 12 13 struct Edge { 14 int to, cap, cost, next; 15 } edge[MAXM * 2]; 16 17 inline void init() { 18 for(int i = 0; i <= n; i++ ) { 19 first[i] = -1; 20 } 21 sign = 0; 22 } 23 24 inline void add_edge(int u, int v, int cap, int cost) { 25 edge[sign].to = v, edge[sign].cap = cap, edge[sign].cost = cost; 26 edge[sign].next = first[u], first[u] = sign ++; 27 edge[sign].to = u, edge[sign].cap = 0, edge[sign].cost = -cost; 28 edge[sign].next = first[v], first[v] = sign ++; 29 } 30 31 int dist[MAXN], inq[MAXN], pre[MAXN], incf[MAXN]; 32 33 bool spfa(int s, int t) { 34 for(int i = 1; i <= n ; i++ ) { 35 dist[i] = INF, inq[i] = 0; 36 } 37 queue<int>que; 38 que.push(s), inq[s] = 1, dist[s] = 0; 39 incf[s] = 0x3f3f3f3f; 40 while(!que.empty()) { 41 int now = que.front(); 42 que.pop(); 43 inq[now] = 0; 44 for(int i = first[now]; ~i; i = edge[i].next) { 45 int to = edge[i].to, cap = edge[i].cap, cost = edge[i].cost; 46 if(cap > 0 && dist[to] > dist[now] + cost) { 47 dist[to] = dist[now] + cost; 48 incf[to] = min(incf[now], cap); 49 pre[to] = i; 50 if(!inq[to]) { 51 que.push(to); 52 inq[to] = 1; 53 } 54 } 55 } 56 } 57 return dist[t] != INF; 58 } 59 60 void update(int s, int t) { 61 int x = t; 62 while(x != s) { 63 int pos = pre[x]; 64 edge[pos].cap -= incf[t]; 65 edge[pos ^ 1].cap += incf[t]; 66 x = edge[pos ^ 1].to; 67 } 68 max_flow += incf[t]; 69 min_cost += dist[t] * incf[t]; 70 } 71 72 void minCostMaxFlow(int s, int t) { 73 while(spfa(s, t)) { 74 update(s, t); 75 } 76 } 77 78 int main() 79 { 80 while(~scanf("%d %d %d %d", &n, &m, &s, &t)) { 81 init(); 82 for(int i = 1; i <= m; i++ ) { 83 int u, v, cap, cost; 84 scanf("%d %d %d %d", &u, &v, &cap, &cost); 85 add_edge(u, v, cap, cost); 86 } 87 max_flow = min_cost = 0; 88 minCostMaxFlow(s, t); 89 printf("%d %d\n", max_flow, min_cost); 90 } 91 92 return 0; 93 }
以上是关于最小费用最大流(luogu P3381 模板最小费用最大流)的主要内容,如果未能解决你的问题,请参考以下文章