题目链接

题目描述

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

输入输出格式

输入格式:

 

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

 

输出格式:

 

一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

 

输入输出样例

输入样例#1: 
4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
输出样例#1: 
50 280

 

费用流模板:

在最大流的前提下,费用最小。由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 }