网络流——最小费用最大流模板

#zkw费用流#

参考网址: https://artofproblemsolving.com/community/c1368h1020435

zkw大佬的改进:①在dfs的时候可以实现多路增广②KM算法节省SPFA时间(然而我这里没有KM,要问为什么,当然是因为我不会了orz);

but,参考了另外的博客,修修补补又三年~

  1 #include <algorithm>
  2 #include <iostream>
  3 #include <cstring>
  4 #include <cstdio>
  5 #include <queue>
  6 #include <cmath>
  7 using namespace std;
  8 const int maxv= 200010;
  9 const int maxe= 2000010;
 10 const int INF= 0x3f3f3f3f;
 11
 12 struct ENode
 13 {
 14     int to;
 15     int c;
 16     int f;
 17     int Next;
 18 };
 19 ENode edegs[maxe];
 20 int Head[maxv], tnt;
 21 void init()
 22 {
 23     memset(Head, -1, sizeof(Head));
 24     tnt= -1;
 25 }
 26 void Add_ENode(int a, int b, int _c, int _f)
 27 {
 28     ++ tnt;
 29     edegs[tnt].to= b;
 30     edegs[tnt].c= _c;
 31     edegs[tnt].f= _f;
 32     edegs[tnt].Next= Head[a];
 33     Head[a]= tnt;
 34     ++ tnt;
 35     edegs[tnt].to= a;
 36     edegs[tnt].c= 0;
 37     edegs[tnt].f= -_f;
 38     edegs[tnt].Next= Head[b];
 39     Head[b]= tnt;
 40 }
 41
 42 bool vis[maxv];  //访问标记
 43 int dist[maxv];  //每个点的距离标号,其实就是dis[];
 44 inline bool spfa(int s, int t)
 45 {
 46     memset(vis, 0, sizeof(vis));
 47     memset(dist, INF, sizeof(dist));
 48     dist[t]= 0;
 49     vis[t]= 1;//首先SPFA我们维护距离标号的时候要倒着跑,这样可以维护出到终点的最短路径
 50     deque<int> q;
 51     q.push_back(t);//使用了SPFA的SLF优化(SLF可以自行百度或Google)
 52
 53     while(!q.empty())
 54     {
 55         int u= q.front();
 56         q.pop_front();
 57         for(int k= Head[u]; k!= -1; k=edegs[k].Next)
 58         {
 59             int v= edegs[k].to;
 60             if(edegs[k^1].c&& dist[v]> dist[u]- edegs[k].f)
 61             {
 62                 /*首先c[k^1]是为什么呢,因为我们要保证正流,但是SPFA是倒着跑的,
 63                 所以说我们要求c[k]的对应反向边是正的,这样保证走的方向是正确的*/
 64                 dist[v]= dist[u]- edegs[k].f;
 65                 /*因为已经是倒着的了,我们也可以很清楚明白地知道建边的时候反向边的边权是负的,
 66                 所以减一下就对了(负负得正)*/
 67                 if(!vis[v])
 68                 {
 69                     vis[v]= 1;
 70                     /*SLF优化*/
 71                     if(! q.empty()&& dist[v]< dist[q.front()])q.push_front(v);
 72                     else q.push_back(v);
 73                 }
 74             }
 75         }
 76         vis[u]=0;
 77     }
 78     return dist[s]< INF;//判断起点终点是否连通
 79 }
 80
 81 int ans; //ans:费用答案
 82 inline int dfs_flow(int now, int c_max, int t)
 83 {
 84     /*这里就是进行増广了,一次dfs进行了多次增广*/
 85     if(now== t)
 86     {
 87         vis[t]=1;
 88         return c_max;
 89     }
 90     int ret= 0, a;
 91     vis[now]=1;
 92
 93     for(int k=Head[now]; k!= -1; k= edegs[k].Next)
 94     {
 95         int v= edegs[k].to;
 96         if(! vis[v]&& edegs[k].c&& dist[v]== dist[now]- edegs[k].f)
 97         {
 98             /*这个条件就表示这条边可以进行増广*/
 99             a= dfs_flow(v, min(edegs[k].c, c_max- ret), t);
100             if(a)
101             {
102                 /*累加答案,加流等操作都在这了*/
103                 ans+= a* edegs[k].f; /*流过时按流量单位计费*/
104                 //ans+= edegs[k].f; /*流过时费用固定*/
105                 /**注意上面两句指令的区别*/
106                 edegs[k].c-= a;
107                 edegs[k^1].c+= a;
108                 ret+= a;
109             }
110             if(ret== c_max)break;
111         }
112     }
113     return ret;
114 }
115
116 inline int Min_Cost_Flow(int s, int t)
117 {
118     int flow= 0;
119     ans= 0;  //费用清零
120     while(spfa(s, t))
121     {
122         /*判断起点终点是否连通,不连通说明满流,做完了退出*/
123         vis[t]= 1;
124         while(vis[t])
125         {
126             memset(vis, 0, sizeof vis);
127             flow+= dfs_flow(s, INF, t);//一直増广直到走不到为止(这样也可以省时间哦)
128         }
129     }
130     return flow;//这里返回的是最大流,费用的答案在ans里
131 }
132 int main()
133 {
134     int n, m, s, t;
135     scanf("%d %d %d %d", &n, &m, &s, &t);
136     init();
137     for(int i= 0; i< m; i ++)
138     {
139         int a, b, c, f;
140         scanf("%d%d%d%d", &a, &b, &c, &f);
141         Add_ENode(a, b, c, f);
142     }
143     printf("%d ", Min_Cost_Flow(s, t));
144     printf("%d\n", ans);
145     return 0;
146 }

end;

原文地址:https://www.cnblogs.com/Amaris-diana/p/11328332.html

时间: 2024-08-30 00:11:12

网络流——最小费用最大流模板的相关文章

poj 2135 Farm Tour (最小费用最大流模板)

网络流的费用: 在实际应用中,与网络流有关的问题,不仅涉及流量,而且还有费用的因素.网络的每一条边(v,w)除了给定容量cap(v,w)外,还定义了一个单位流量费用cost(v,w) 最小费用最大流问题 给定网络G,要求G的一个最大用流flow,使流的总费用最小. 求解MCMF问题的算法: 最小费用最大流最常用和基本的算法我们可以称它为最小费用路算法,其思想与求最大流的增广路算法类似,不断在残流网络中寻找从源s到汇t的最小费用路,即残流网络中从s到t的以费用为权的最短路,然后沿最小费用路增流,直

POJ2135Farm Tour(最小费用最大流模板)

题目链接:http://poj.org/problem?id=2135 题意:农场主想从1到n,然后从n到1,每条边最多走一次,不能走重复的路,问最短距离是多少. 建图:取超级源点s,并与房子连一条边,容量为2,费用为0:取barn与超级汇点 t 的边的容量为2,费用为0 房子与barn的费用为距离,容量为1 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring>

网络流(最小费用最大流):POJ 2135 Farm Tour

Farm Tour Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 2135 64-bit integer IO format: %lld      Java class name: Main When FJ's friends visit him on the farm, he likes to show them around. His farm compris

POJ2135 最小费用最大流模板题

练练最小费用最大流 此外此题也是一经典图论题 题意:找出两条从s到t的不同的路径,距离最短. 要注意:这里是无向边,要变成两条有向边 #include <cstdio> #include <cstring> #define MAXN 1005 #define MAXM 10005 #define INF 0x3f3f3f3f struct Edge { int y,c,w,ne;//c容量 w费用 }e[MAXM*4]; int n,m,x,y,w; int s,t,Maxflow

Doctor NiGONiGO’s multi-core CPU(最小费用最大流模板)

题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=693 题意:有一个 k 核的处理器和 n 个工作,全部的工作都须要在一个核上处理一个单位的时间,每一个核在不同一时候间处理同一个工作的花费是递增的,每一个核一次仅仅能处理一个工作,求运用k个核处理这n个工作的最小花费. 分析: 分析可知,求处理全部工作的最小花费,而每次选择怎么处理我们能够通过容量都为1的边来让网络流处理,这样就转化为最小费用最大流. 首先设一个超级源点s,连接全部的工作

网络流--最小费用最大流 (理解)

1.什么是最小费用最大流问题 上篇文章我们讲解了最大流问题,那什么是最小费用最大流呢?听名字就可以看出,我们要在满足最大流的同时找到达成最大流的最小费用. 对于一个网络流,最大流是一定的,但是组成最大流的费用是可以不同的,这里就有了在最大流网络上产生的费用流网络,就有了最小花费问题. 简单来说,就是满足最大流的路径可能有多条,我们要从这多条路径中找到一条花费代价最小的路径.所以最大流是解决这类问题的前提 2.EK算法 + SPFA 最短路   我们用每条边单位流量的花费作为边权,假如一条合法路径

poj 2195 最小费用最大流模板

/*Source Code Problem: 2195 User: HEU_daoguang Memory: 1172K Time: 94MS Language: G++ Result: Accepted Source Code */ #include <iostream> #include <stdio.h> #include <queue> #include <math.h> #include <string.h> using namespa

HDU 1533--Going Home【最小费用最大流 &amp;&amp; 模板】

Going Home Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3452    Accepted Submission(s): 1771 Problem Description On a grid map there are n little men and n houses. In each unit time, every

Farm Tour(最小费用最大流模板)

Farm Tour Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 18150   Accepted: 7023 Description When FJ's friends visit him on the farm, he likes to show them around. His farm comprises N (1 <= N <= 1000) fields numbered 1..N, the first of