最小费用最大流模板
来源:互联网 发布:选车软件 编辑:程序博客网 时间:2024/05/29 16:56
一、最小费用最大流的模型
在保证流量最大的前提下,所需的费用最小,这就是最小费用最大流问题.
带有费用的网络流图: G=(V,E,C,W)
V:顶点; E:弧;C:弧的容量;W:单位流量费用。
任意的弧<i,j>对应非负的容量c[i,j]和单位流量费用w[i,j]。满足:
① 流量f是G的最大流。
② 在f是G的最大流的前提下,流的费用最小。
F是G的最大流的集合(最大流不止一个):
在最大流中寻找一个费用最小的流 f.
二、最小费用最大流的算法
基本思路:
1. 最小费用可增广路
2. 路径s到t的长度即单位流量的费用。
ps:是网络流EK算法的改进,在求增广路径的时候,把bfs改为带权的spfa,每次求权值最小的增广路。
ps:要注意一点,逆边cost[i][j] = -cost[j][i],不能忘了加上去。
//邻接矩阵。#include<iostream>#include<stdio.h>#include<string.h>using namespace std;#define Max 310#define inf 0x3f3f3f3fint n, ans,en,st;int cap[Max][Max], pre[Max];int cost[Max][Max], dis[Max];int que[Max];bool vis[Max];bool spfa(){ // 源点为0,汇点为n。 int i, head = 0, tail = 1; for(i = 1; i <= n; i ++){ dis[i] = inf; vis[i] = false; } dis[st] = 0; que[0] = st; vis[st] = true; while(tail != head){ // 循环队列。 int u = que[head]; for(i = 1; i <= n; i ++) if(cap[u][i] && dis[i] > dis[u] + cost[u][i]){ // 存在路径,且权值变小。 dis[i] = dis[u] + cost[u][i]; pre[i] = u; if(!vis[i]){ vis[i] = true; que[tail ++] = i; if(tail == Max) tail = 0; } } vis[u] = false; head ++; if(head == Max) head = 0; } if(dis[en] == inf) return false; return true;} void end(){ int i, sum = inf; for(i = en; i != st; i = pre[i]) sum =sum<cap[pre[i]][i]?sum:cap[pre[i]][i]; for(i = en; i != st; i = pre[i]){ cap[pre[i]][i] -= sum;//cap最大流量 cap[i][pre[i]] += sum; ans += cost[pre[i]][i] * sum; // cost[][]记录的为单位流量费用,必须得乘以流量。 }} int main(){ ... ans = 0; while(spfa()) end(); ... return 0;}
//邻接表。#include<iostream>using namespace std; struct{ int v, cap, cost, next, re; // re记录逆边的下标。}edge[eMax];int n, m, ans;int k, edgeHead[nMax];int que[nMax], pre[nMax], dis[nMax];bool vis[nMax]; void addEdge(int u, int v, int ca, int co){ edge[k].v = v; edge[k].cap = ca; edge[k].cost = co; edge[k].next = edgeHead[u]; edge[k].re = k + 1; edgeHead[u] = k ++; edge[k].v = u; edge[k].cap = 0; edge[k].cost = -co; edge[k].next = edgeHead[v]; edge[k].re = k - 1; edgeHead[v] = k ++;} bool spfa(){ // 源点为0,汇点为n。 int i, head = 0, tail = 1; for(i = 0; i <= n; i ++){ dis[i] = inf; vis[i] = false; } dis[0] = 0; que[0] = 0; vis[u] = true; while(tail > head){ // 这里最好用队列,有广搜的意思,堆栈像深搜。 int u = que[head ++]; for(i = edgeHead[u]; i != 0; i = edge[i].next){ int v = edge[i].v; if(edge[i].cap && dis[v] > dis[u] + edge[i].cost){ dis[v] = dis[u] + edge[i].cost; pre[v] = i; if(!vis[v]){ vis[v] = true; que[tail ++] = v; } } } vis[u] = false; } if(dis[n] == inf) return false; return true;} void end(){ int u, p, sum = inf; for(u = n; u != 0; u = edge[edge[p].re].v){ p = pre[u]; sum = min(sum, edge[p].cap); } for(u = n; u != 0; u = edge[edge[p].re].v){ p = pre[u]; edge[p].cap -= sum; edge[edge[p].re].cap += sum; ans += sum * edge[p].cost; // cost记录的为单位流量费用,必须得乘以流量。 }} int main(){ ... ans = 0; while(spfa()) end(); ... return 0;}
1 0
- 模板[最小费用最大流]
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流,模板
- 最小费用最大流模板
- 最小费用最大流 模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 一个网站初级运营需要了解的书籍、网站、工具
- wxPython学习笔记(二)
- 2.1.5 Median of Two Sorted Arrays
- 表情配置
- 如何培养交互设计师的数据分析能力
- 最小费用最大流模板
- 科技创业公司那些上百亿美元的估值怎么算出来--夏雨青
- 如何一直保持测试工作的热情
- hdu4932 小贪心
- OHS简单安装与系统配置
- Elasticsearch索引重建(Rebuild)
- linux与arm的交叉编译的过程(小编用的目标板是arm tiny6410 )
- ny 352 数乌龟
- ios ViewController 页面跳转