网络流算法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
}
奶牛的新年晚会---最大流问题
• 奶牛们要举办一次别开生面的新年晚会。每头 奶牛会做 一些不同样式的食品(单位是盘)。 到时候他们会把自己最 拿手的不超过k样食品 各做一盘(例如一个馅饼,一根香肠和一片面 包)带到晚会,和其他奶牛一起 分享。但考虑 到食品太多会浪费掉,他们给每种食品的总盘 数都规定了一个不同的上限值。这让他们很伤 脑筋, 究竟应该怎样做,才能让晚会上食品的 总盘数尽量的多呢?
网络流
网络流初步
网络流是一个适用范围相当广 的模型,相关的算法也非常多 • 增光路算法 Edmnds-Karp • Dicnic算法 • 预留推进算法 可以解决的问题: • 最大流问题 • 最小割最大流 • 最小费用最大流 • 多源多汇网络的可行流 • 容量有上下界的网络的最大流
最大流问题
• 假设你需要把一些物品从节点s(称为源点)运 送到节点t(称为汇点),可以从其他节点中转。 图(a)中各条有向边的权表示最多能有多少个 物品从这条边的起点直接运送到终点。例 如最 多可以有9个物品从节点v3运送到v2。
16 10 9 7 10 7/7
v1 12 v3
s
t
v1 12/12 v3
11/16
s
4/9
15/20
t
1/4 8/13
20 4 13
4
v2 14 v4
4/4
v2 11/14 v4
(a)
(b)
(b)展示了一种可能的最优方案,其中每条边
中的第一个数字表示实际运送的物品数目,而第
二个数字就是题目中的上限。
•
for(int v=0;v<=n;v++)
• if(!a[v]&&cap[u][v]>flow[u][v])
•
//找到新结点v
•
{ p[v]=u;q.push.(); //记录v的
父亲,并加入FIFO队列
•
a[v]=a[u]<?cap[u][v]-
dlow[u][v]; //s-v路径上的最小残量
v1 12/12 v3
15/20
1/4 8/13
s
t
4/4
v2 11/14 v4
(a)
v1 12 v3
5
5 11 3
15
s
45
t
5
13
3
4
v2
v4
11
Hale Waihona Puke Baidu(b)
增广路算法
v1 12/12 v3
v1 12 v3
11/16 10 4/9 7/7
11
15/20
1/4 8/13
5
5 11 3
15
s
ts
45
7
t
最大流问题
Maximum-Flow Problem 对于一条边(u,v),它的物品上限称为容量 (capacity),记为c(u,v) 实际运送的物品称为流量(flow),记为f(u,v)。 (对于不存在的边(u,v),c(u,v)==0);
最大流问题的目标是把最多的物品从s运送到t, 而其他节点都只是中转,因此对于除了结点s 和t外的任意结点u。从s运送来的物品数目等于 到达t的物品数目,而这是我们最大化的目标。
增广路算法
• 当且仅当残量网络中不存在s-t有向道路(增光 路)时,此时的流是从s到t的最大流。
• 找任意路径”最简单的办法无疑是用DFS, 但很容易找出让它很慢的例子。一个稍微好 一点的方法就是使用BFS,它足以应对数据 不刁钻的网络流题目。这就是Edmonds-Karp 算法。在下面的代码中,源点和汇点保存在 变量s和t中,运行结束后,s-t的净流量保存 在变量f中。
奶牛的新年晚会---最大流问题
• 例如:有4头奶牛,每头奶牛最多可以带3盘食 品。一共有5种食品,它们的数量上限是2、2、 2、2、3。奶牛1会 做食品1~4,奶牛2会做食 品2~5,奶牛3会做食品1、2、4, 奶牛4会做 食品1、2、3。
奶牛的新年晚会---最大流问题
那么最多可以带9盘食品到晚会上。 即奶牛1做 食品2…4,奶牛2做食品3…5,奶牛3做食品1、 2, 奶牛4做食品1。这样,4种食品各有2、2、 2、2、1盘,没有超过它们各自的限制;
增广路算法
• queue<int>q;
• menset(flow,0,sizeof(flow)); f=0;
• for(;;)
• { memset(a,0,zizeof(a));
• a[s]=INF; q.push(s);
• while(!q.empty()) //BFS找增广路
•{
•
int u=q.front();q.pop();
• 把图(a)中的每条边上容量与流量之差 (称为残余容量,简称残量)计算出, 得到图(b)中的残量网络(residual network)。
增广路算法
• 把图(a)中的每条边上容量与流量之差
(称为残余容量,简称残量)计算出,
得到图(b)中的残量网络(residual
network)。
11/16 10 4/9 7/7 11 7
5
4/4
13
3
4
v2 11/14 v4
v2
v4
11
(a)
v1 12/12 v3
11/16 10 9 7/7
19/20
1/4 12/13
s
t
4/4
v2 11/14 v4
(b)
v1 12 v3
5
5 11
15
11
s
3
9
7
t
1
12
3
4
v2
v4
11
(d)
增广路定理
• 残量网络中任何一条从s到t的有向道路都对 应一条原图中的增广路(augmenting path)--------只要求出道路中所有残量的最小值d,把 对应的所有边是上的流量增加d即可,这个 过程称为增广(augmenting)。不难验证,如 果增广前的流量满足3个条件,增广后仍然 满足。显然,只要残量网络中存在增广路, 流量就可以增大。可以证明它的逆命题也成 立:如果残量网络中不存在增广路,则当前 就是最大流。这就是著名的增光路定理。
•
}
•}
if(a[t]==0) break;
//找不到,
则当前已经是最大流
for(int u=t;u!=s;u=p[u]) //
从汇点往回走
{
flow[p[u]][u] +=a[t];
//更新正向流量
flow[u][p[u]] -=a[t];
//更新反向流量
}
f+=a[t];
//更新从s流出的总流量
最大流问题
容量c和容量f满足3个性质: ➢容量限制:f(u,v)<=c(u,v) ➢斜对称性:f(u,v)=-f(v,u) ➢流量平衡:对除了结点s和t外的任意结 点u, 问题的目标:最大化 即从s点流出的净流量(它也等于流入 的t点的净流量)。
增广路算法
• 算法思想:从零流(所有边的流量均为0) 开始不断增加流量,保持每次增加流量 后都满足容量限制,斜对称性和流量平 衡3个条件。