最小费用最大流(luogu P3381 【模板】最小费用最大流)

题目链接

题目描述

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

输入输出格式

输入格式:

第一行包含四个正整数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 }

原文地址:https://www.cnblogs.com/Q1143316492/p/8972011.html

时间: 2024-10-09 04:55:00

最小费用最大流(luogu P3381 【模板】最小费用最大流)的相关文章

luogu p4015(最小费用最大流)

传送门 题意: 有\(m\)个仓库和\(n\)个零售商,第\(i\)个仓库送到第\(j\)个零售商需要花费\(v[i][j]\)元.现在需要让仓库的供给量以及零售商的收获量相同,问最小花费以及最大花费. 分析: 相当经典的最小费用最大流的模型.因为要保证供给以及收获相同,即代表着流量平衡,因此我们可以让超级源点\(sp\)跟对应的仓库连一条流量为\(a_i\),费用为\(0\)的边,同时让对应的零售商跟超级汇点\(ep\)连一条流量为\(b_i\),费用为\(0\)的边.而对于仓库与零售商,我们

HDU 3488--Tour【最小费用最大流 &amp;&amp; 有向环最小权值覆盖 &amp;&amp; 经典】

Tour Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 2308    Accepted Submission(s): 1156 Problem Description In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 3000

hdu 4009 Transfer water(最小树形图:有向图的最小生成树模板)

题目: 链接:点击打开链接 题意: 有n个村庄,要求使得每个村庄都能得到水的最小费用.每个村庄可以通过挖井或从其他村庄修水路获得水.挖井的费用是房子的高度乘以X,修水道的费用和有向图边的起点和终点的高度有关. 思路: 代码: #include <iostream> #include <cstdio> #include <cmath> #include <cstring> using namespace std; #define inf 0x3f3f3f3f

delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)

1.所有程序最小化 uses ComObj; var shell : OleVariant; begin shell := CreateOleObject('Shell.Application'); shell.minimizeAll; end; 2.最小化其他程序 spy++ 查找要最小化的程序classname var Indicador :Integer; begin // Find the window by Classname Indicador := FindWindow(PChar

最大流 Dinic + Sap 模板

不说别的,直接上模板. Dinic+当前弧优化: struct Edge{ int x,y,c,ne; }e[M*2]; int be[N],all; int d[N],q[N]; int stack[N],top;//栈存的是边 int cur[N];//当前弧优化 void add(int x, int y, int z)//需保证相反边第一个为偶数 { e[all].x=x; e[all].y=y; e[all].c=z; e[all].ne=be[x]; be[x]=all++; e[a

ACdream 1135(MST-最小生成树边上2个值,维护第一个最小的前提下让另一个最小)

F - MST Time Limit: 2000/1000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others) SubmitStatus Problem Description Given a connected, undirected graph, a spanning tree of that graph is a subgraph that is a tree and connects all the vertices to

[luogu P3384] [模板]树链剖分

[luogu P3384] [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数

最大流ISAP算法模板

这两天学习了最大流,下面是ISAP算法模板: const int inf = 0x3fffffff; template <int N, int M> struct Isap { int top; int d[N], pre[N], cur[N], gap[N]; struct Vertex{ int head; } V[N]; struct Edge{ int v, next; int c, f; } E[M]; void init(){ memset(V, -1, sizeof(V)); t

洛谷 P3376 【模板】网络最大流

P3376 [模板]网络最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,求出其网络最大流. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表示点的个数.有向边的个数.源点序号.汇点序号. 接下来M行每行包含三个正整数ui.vi.wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi) 输出格式: 一行,包含一个正整数,即为该网络的最大流. 输入输出样例 输入样例#1: 复制 4 5 4 3 4 2 30 4 3 20 2 3 20 2 1 30