•前言
最近在看 Edelweiss 的网络流建模汇总
来学习网络流的建模技巧
毕竟网络流的题难点就在于如何建图,其余大部分就是套路了
于是也写下自己的想法和思路
(虽然一直在借鉴大佬思路)
•最大流
•POJ 1149 Pigs
【题目大意】
有 M 个猪圈,每个猪圈里初始时有若干头猪pig[i]。一开始所有猪圈都是关闭的。依次来了 N 个顾客,每个顾客分别会打开指定的几个猪圈,从中买若干头猪。每 个顾客分别都有他能够买的数量的上限。每个顾客走后,他打开的那些猪圈中的 猪,都可以被任意地调换到其它开着的猪圈里,然后所有猪圈重新关上。问总共 最多能卖出多少头猪。(1 <= N <= 100, 1 <= M <= 1000)
【思路】
设一个s点为源点,一个t点为汇点
每来一个顾客$m+i$(顾客从m+1开始编号),如果他所拥有钥匙的猪圈还未被打开过,那连一条源点和他 流量为此猪圈的猪的数量$(s,i,pig[i])$的边
如果他所拥有钥匙的猪圈$index$被打开过,那连一条前一个打开的人和他 流量为INF的边$(vis[index],i,INF)$
每个顾客与汇点连一条流量为此顾客购买力的边$(m+i,t,buy)$
其实就是把可以调换的猪圈混合在了一起,s-t流和调换猪对应了起来
【样例】
3 3
3 1 10
2 1 2 2
2 1 3 3
1 2 3
7
【代码】
POJ 1149 Pigs
•POJ 3281 Dining
【题目大意】
有 F 种食物和 D 种饮料,每种食物或饮料只能供一头牛享用,且每头牛只享用一 种食物和一种饮料。现在有 N 头牛,每头牛都有自己喜欢的食物种类列表和饮 料种类列表,问最多能使几头牛同时享用到自己喜欢的食物和饮料。( 1 <= F <= 100, 1 <= D <= 100, 1 <= N <= 100)
【思路】
以往一般都是左边一个点集表示供应并与源相连, 右边一个点集表示需求并与汇相连。现在不同了,供应有两种资源,需求仍只有 一个群体,
根据这个群体与两种资源的联系来看,食物和饮料之间并没有直接联系,而是牛与食物,牛与饮料分别有联系
可以把牛放在两种资源中间,源点与食物相连,饮料与汇点相连,然后牛在中间食物与牛相连 牛与饮料相连(t->食物->牛->饮料->汇点)
但是会出现一只牛吃多种食物多种饮料的情况所以要把牛拆点拆成(牛,牛',1)为了保证只能吃一次,两者之间流量为1
【样例】
4 3 3
2 2 1 2 3 1
2 2 2 3 1 2
2 2 1 3 1 2
2 1 1 3 3
3一只牛会吃多个套餐 一只牛只能吃一个套餐
【代码】
POJ 3281 Dining
•JOJ 2453 Candy
【题目大意】
有$N$颗糖果和$M$个小孩,老师现在要把这$N$颗糖分给这$M$个小孩。每个小孩$i$对每颗糖$j$都有一个偏爱度$A_{ij}$,如果他喜欢这颗糖$A_{ij} = 2$,否则 $A_{ij} = 1$。小孩$i$觉得高兴当且仅当$∑C_{ij}×A_{ij} >= B_{i},j=1,2,…,N$,若他分得了糖 $j$,$C_{ij} = 1$否则$C_{ij} = 0$。问能否合理分配这$N$颗糖,使得每个小孩都觉得高兴。($1 <= N <= 100,000$, $1 <= M <= 10, 0 <= B_{i} <= 1,000,000,000$)
【思路】
一种最直观的想法就是每颗糖 i 作为一个点并连边(s, i, ?),每个小孩 j 作为一个 点并连边(j, t, Bj)。若小孩 j 喜欢糖果 i 则连边(i, j, 2),否则连边(i, j, 1),然后求一 次最大流看是否等于∑Bj,但是源点和糖之间的流量无法确定,为什么呢?因为一旦选定一条边之后就只能从这条边流而不能再进入其他的出边
假设流量为1,那如果小孩喜欢此糖的话,流量需要为2,所以pass!
假设流量为2,如果小孩不喜欢的话,流量需要为1,且不能再流向其他小孩了,为2的话就不能保证不再流量另一个不喜欢的小孩,所以pass!
现在转换一下思路,由于问的是否所有孩子都能高兴,为了尽量让孩子高兴,所以每颗糖都会分出去,即$C_{ij} = 1$
假设有$x$个$A_{ij}=2$,其余$A_{ij}=1$,则 $∑C_{ij}×A_{ij} =∑1*A_{ij}=N+x$,则所有小孩都高兴即为$N+x>=∑B$j
所以只考虑可以额外提供1点高兴值的糖果和小孩,因为贡献值从2变为1减半了,所以小孩到汇点的流量也需要减半,
(达到快乐就行了 不能让他多吃了糖果 还有其他小孩呢)
这样就只需要判断小孩是不是喜欢这块糖了,如果喜欢的话,就连边流量为1,如果不喜欢的话就不连边,或者流量为0也行
【样例】
1
4 3
1 2 1
2 1 1
1 1 2
1 2 2
3 2 2
1 1
YES【代码】
JOJ 2453 Candy
•ZOJ 2760 How Many Shortest Path
【题目大意】
给定一个带权有向图 G=(V, E)和源点 s、汇点 t,问 s-t 边不相交最短路最多有几 条。(1 <= N <= 100)
【思路】
分别以源点和汇点为起点跑dijkstra,得到最短路图,令最短路的边流量都为1,在最短路上跑最大流,得到独立路径条数
类似于hdu 6852,不过最短路图加边时令流量为1
•WOJ 1124 Football Coach
【题目大意】
有 N 支球队,互相之间已经进行了一些比赛,还剩下 M 场没有比。现在给出各 支球队目前的总分以及还剩下哪 M 场没有比,问能否合理安排这 M 场比赛的结 果,使得第 N 支球队最后的总分大于其他任何一支球队的总分。已知每场比赛 胜者得 2 分,败者 0 分,平局则各得 1 分。(1 <= N <= 100, 0 <= M <= 1000)
【思路】
首先利用贪心的思想,让第N支球队赢剩下的所有他参加的比赛,如果此时仍有球队的总分大于等于球队 N 的总分$score[N]$,则已经不可能满足要求;
如果满足的话,想要N赢,那其他的球队i的得分肯定比$score[N]$小,对于除与N以外球队来说,设现在第i支球队得分为$score[i]$,所有比赛结束后得分为$score[i']$
即$score[i']
对于除与N相关以外的比赛来说,源点到比赛j的容量为2,(s,j,2),每场比赛向与其关联的两支球队 u, v 连边(j, u, 2), (j, v, 2)
【样例】
5 4
4 4 1 0 3
1 3
2 3
3 4
4 5
NO
•SGU 326 Perspective
【题目大意】
NBA 某小组内有 N 支球队,小组内以及小组间已经进行了若干场比赛。现在给 出这 N 支球队目前胜利的场数、还剩多少场没有比(包括小组内和小组间)以 及小组内任意两支球队之间还剩多少场没有比,问能否合理安排剩下的所有比赛, 使得球队 1 最后成为小组冠军或者并列冠军。 (2 <= N <= 20, 0 <= x <= 10000, x 表示其他任何输入)
【思路】
跟上面WOJ 1124 Football Coach差不多,先令与球队1相关的赛事都让球队1赢,由于想让1赢,那么应该尽可能加大其他队与1的差距 ,
所以令除1以外的小组间的赛事都输,注意这个是可以并列,所以每支球队到汇点的容量为$score[N]-score[i]$
所有小组内的比赛 i(不包括与球队 1 相关的比赛)作为一个点并加边$(s, i, num[i])$,每支球队(不包括球队 1)作为一个点并加边$(j, t, score[N]-score[i])$,每场 比赛向与其关联的两支球队 u, v 连边$(i, u, ∞), (i, v, ∞)$。至于其他球队小组间的 比赛,直接让他们输掉就好,不用管。若最大流等于$∑num[i]$则可以满足要求。
•SPOJ 287 Smart Network Administrator
【题目大意】
一座村庄有 N 户人家。只有第一家可以连上互联网,其他人家要想上网必须拉 一根缆线通过若干条街道连到第一家。每一根完整的缆线只能有一种颜色。网管 有一个要求,各条街道内不同人家的缆线必须不同色,且总的不同颜色种数最小。 求在指定的 K 户人家都能上网的前提下,最小的不同颜色种数。(1 <= N <= 500)
【思路】
以第一家作为汇点 t,K 户人家中的每一户 i 作为一个点并连边$(s, i, 1)$,对每条街道$(u, v)$,连边$(u, v, c), (v, u, c),c=∞$。 这样求完最大流后每一条 s-t 流均对应一户人家的缆线,而各条街道内的流量表 示有多少户人家的缆线同时穿过该街道,那么这个流量就是只考虑该条街道的时候最少的不同颜色种数。那么答案是否就是所有街道的不同颜色种数的最大值呢? 当然不是!最大流只保证总流量最大,而不会去管每条流具体该往哪儿流,所以 这么做不一定能得到最优解。我们只要稍微修改这个模型就一定能保证得到最优 解:去对c进行二分,强制 c 等于某个值 limit,再对网络求最大流,如果等于 K,说明用 c 种不同 的颜色已经足够了;如果小于 K,说明 c 种还不够,还需要往高了调。同时此处 的单调性也很明显:c 越高越容易满足要求。
【样例】
5 5 4
2 3 4 5
1 2
1 3
2 3
2 4
3 54
一种颜色代表一根线,同一根线n种颜色代表流量为n
•SPOJ 962 Intergalactic Map
【题目大意】
在一个无向图中,一个人要从 1 点赶往 2 点,之后再赶往 3 点,且要求中途不 能多次经过同一个点。问是否存在这样的路线。(3 <= N <= 30011, 1 <= M <= 50011)
【思路】
由于是从1到2,再从2到3,可以看做是从2到1,从2到3有没有独立的路径,没有重合的点
为了保持点不重合,我们可以把i点拆开连边$(i,i',1)$,其中$i$点为入点,$i'$点为出点
以2的出点为源点,以0为汇点,为了必须经过1,3点,对1和3的出点和汇点连边$(1',t,1),(3',t,1)$
对于输入的边$(u,v)$,利用入点和出点的关系连接即$(u',v,1),(v',u,1)$
然后判断从源点到汇点的路径是否是两条
最后 输入的时候,可能有边不在1~n的范围内,需要跳过这些边。
【代码】
spoj Intergalactic Map