网络流复健
好长时间不做网络瘤了,啥也不会,于是复健了下。
导致现在我看到网络瘤就恶心。
大部分都是题,还有一小部分也是题。
在这里放个歌词罢。
\(\textbf{Born in the month of darkness}\)
Before the Great Burning, before the wars
A time of nothing, but hills and shores
The smoke of cities, and fields of rye
No eyes or voices beyond the sky
Believers roamed from town to town
They spied every baby born, up and down
Scouring the land for a child to use
And ponderous, esoteric clues
A crumbling black city, an outcast found
Father a monster, mother under the ground
A beggar, a mongrel, a boy with no shoes
He fell to their hands to cage and abuse
And lo! In the month of darkness
And lo! His name destroyed
And lo! He still whispers in silence
And lo! He went into the void
They were drawn to a light, a waning gray
His face was blank, he had nothing to say
He watched and waited, they painted his eyes
They colored his clothing with pigments and dyes
They found a path away from the light
To an ancient tree withered by blight
A sacred altar, encircled in stones
Twin blades of bronze, sharpened on bones
And lo! In the month of darkness
And lo! His name destroyed
And lo! He still whispers in silence
And lo! He went into the void
In the Month of Darkness, seasons destroyed
A ritual killing bound his spirit to the Void
Eyes drained of color, the beggar no more
To become what the Believers waited for
They set him outside, beyond the spheres
Quiet as the night, long like the years
He opened his eyes, as black as a dream
Trying to speak, his only words a scream
And lo! In the month of darkness
And lo! His name destroyed
And lo! He still whispers in silence
And lo! He went into the void
以下用 \((u,v,w)\) 表示网络流建模中从 \(u\) 到 \(v\) 容量为 \(w\) 的边。
用 \((u,v,w,c)\) 表示网络流建模中从 \(u\) 到 \(v\) 容量为 \(w\) ,费用为 \(c\) 的边。
用 \((u,v)\) 表示原图中 \(u\) 与 \(v\) 的连边关系。
酒店之王
发现房间,菜品,客人都有一定的限制。考虑让客人作为流量,求出的最大流即是答案。
如果把房间 \(p_i\) 和菜品 \(q_i\) 的限制都放在客人的同一侧,那么每个房间/菜品只能提供给一个客人的条件将不会被同时满足。所以应该把每位客人当做容量为 \(1\) 的边放在最中间,两头向喜欢的房间 \(p_i\) 或者菜品 \(q_i\) 相连,再连边 \((s,p_i/q_i,1),(q_i/p_i,t,1)\) 表示两者皆只能被选择一次。
跑最大流即可。
[SHOI2001]小狗散步
主人在一个位置走在另一个位置的途中,狗最多只能前往一个景点,一个景点只能经过一次。于是可以将主人的每一段路程看做一个节点 \(x_i\),景点看做 \(y_i\)。处理出第 \(i\) 段路程小狗能够到达的景点 \(y_j\)。连边 \((s,x_i,1),(x_i,y_j,1),(y_i,t,1)\),跑最大流。
输出方案只需要看边 \((x_i,y_j,1)\) 是否满流即可,满流就输出 \(y_j\) 。
追查坏牛奶 Pollutant Control
第一问,一眼顶针,裸的最小割。
第二问问的是最小割中所要割掉的最少割边。
考虑第一问搞完之后的残量网络,所有满流的边都可以成为最小割,将这些满流边的容量设为 \(1\),其他边的容量设为 \(inf\)。此时可以发现每一单位的流量都会表示一条边的割去,为满足条件再对其跑一次最小割即可。
拍照
最大权闭合子图的模型。
对于所有的收入设点 \(x_i\),连边 \((s,x_i,m_i)\)。所有的费用设点 \(y_i\),连边 \((y_i,t,n_i)\)。对于每一种关系,连边 \((x_i,y_i,inf)\)。表示若得到某收入就必须进行某花费,否则就减去该收入。
初始化 $ans=\sum_{i=1}^{M} m_i $,减去上图的最小割即可。
人员雇佣
三个月之前做过的题再看一遍还tm不会😅
依然事最大权闭合子图,但是还要考虑一些东西。
对于第 \(i\) 个人,容易发现选上他之后最多可以有 $\sum_{j=1}^{n} E_{i,j} $ 的贡献,同时还有 \(A_i\) 的费用,分别向源点和汇点进行一个边的连。
但是啊但是,一旦有个人 \(j\) 不雇佣啊,这个b还会造成 \(E_{i,j}\) 负贡献,也就说存在一个 \(-2\times E_{i,j}\) 的贡献差。所以对于每对 \((i,j)\) 还要连边 \((i,j,2\times E_{i,j})\) 表示如果 \(i\) 选 \(j\) 不选,则会造成 \(2\times E_{i,j}\) 的贡献流失掉。
最后初始化 $ans=\sum_{i=1}^n \sum_{j=1}^n E_{i,j} $ ,减去上图的最小割即可。
[TJOI2010]电影迷
有意思,真有意思
依然事最大权闭合子图,但是非常有意逝。
模型其实是一样的,重点在于负贡献与正贡献,正贡献与正贡献,负贡献与负贡献也有关系。
异号的关系就不说了,跟正常模型差不多。
然后手模半天发现同号其实也是一样的。
假设两者同为正贡献的其中一个被割去(不选),说明另一端还可能存在流量,这就会导致源点与汇点之间连通,且之间存在四种类型的边。
-
原来没被割去的负贡献边,割去它表明这部负贡献的电影会被选上。但是如此以来它连着的正贡献边就不用割了,忽略。
-
连接被割去边的正贡献边,割去它表明两部有正贡献的电影都不会选。
-
维护异号之间关系的边,割去它表明不再维护这个关系(减去贡献),但是如此以来它连着的正贡献边就不用割了,忽略。
-
维护同号之间关系的边,割去它表明不再维护这个关系(减去贡献),另一部电影还要选。
综上,直接连就可以,进行一个最小的割。
方格取数问题
考虑位置的限制,题目要求相邻的格子里不能同时有值。
那肯定是最小割,连边 \(inf\) 表示两个位置不能同时选,割去最小的不就行了(😎
但实际上瞎几把连边啥都不是。
遇到棋盘上位置冲突的时候可以想一下黑白染色。横纵坐标之和为偶数的是白格,否则是黑格。容易发现与白格相邻的一定是黑格,那么整个图就是一个二分图,黑白两色与源汇分别相连即可。
进行一个最小的割。
最小路径覆盖问题
有个显然的结论:最小路径覆盖=总点数-最大匹配边数。因为每连一条边路径数量就会减少 \(1\) 。
考虑把每个点拆成入点 \(y_i\) 和出点 \(x_i\),入点最多能匹配一次,出点最多也只能匹配一次,所以连向源汇的边容量都为 \(1\)。中间的话如果 \(i,j\) 在原图有边就连 \((x_i,y_j,1)\)。(容量为 \(1\) 主要是为了判断满流的时候比较好判)
跑最大流,答案为 \(n-ans\) 。按照流量情况输出方案即可。找到所有入边容量为 \(1\) 点然后进行一个 \(\textrm{dfs}\) 的搜。
跑匈牙利也没问题(
部落战争
把能连的边都连上,然后就是最小路径覆盖的裸题。
[AHOI2009]最小割
写上这个题是为了复习一下某些知识(
如果对最小割跑出的残量网络求出所有强联通分量,那么会有:
-
\(s\) 与 \(t\) 不在同一 \(SCC\) 里,如果在的话 \(s\) 与 \(t\) 就会连通,不是最小割了。
-
对于满流边 \((u,v,w)\) ,其能成为最小割的必经边当且仅当 \(u\) 与 \(s\) ,\(v\) 与 \(t\) 在同一 \(SCC\) 中。结合第一条显然。
-
对于满流边 \((u,v,w)\) ,其能成为最小割的可行边当且仅当 \(u\) 与 \(v\) 不在同一 \(SCC\) 中。
考虑反证法,如果它们在同一 \(SCC\) 里,那么就会存在 \(u\) 到 \(v\) 的正向路径,说明此时割去这条边仍然不会断流,因此不能当做最小割的方案。
[CQOI2016]不同的最小割
最小割树,具体证明不会,而且感觉考的概率不是很大。
对于一个无向连通图,建立其最小割树的方法是:
-
随机两个不同的点 \(u,v\),跑出全局的最小割 \(w\) 。在树上加边 \((u,v,w)\)。
-
易知跑完最小割之后所有的点会被分成两个集合,分别在两个集合中递归下去。直到集合中的点少于两个。
最小割树有个好性质是 \(u\) 到 \(v\) 路径上的边权最小值是就是以 \(u\) 为源点,\(v\) 为汇点的最小割。
[NOI2010]海拔
结论是:所有的路口要么海拔是 \(0\) ,要么海拔是 \(1\) ,而且会形成 \(0\) 和 \(1\) 的联通块。证明可以看题解。
所以一定会有那么几条路的人流量会产生体力消耗,而且,总的看起来,它们是整个平面图的一个割。
求最小消耗那肯定是最小割了。
然后信仰 \(\textrm{Dinic}\) 就萎掉力😰
注意到,平面图最小割等于对偶图最短路。
把平面图所分割的平面当做顶点与相邻的平面连边,建出来的就是对偶图,跑最短路即可。
建图的话可能会有些麻烦。
餐巾计划问题
🤔 \(\to\) 🙁 \(\to\) 😦 \(\to\) 😧 \(\to\) 😨 \(\to\) 😰
把每天的餐厅拆成白天 \(x_i\) 和晚上 \(y_i\) 两个点。
-
白天需要 \(r_i\) 条干净餐巾,连边 \((x_i,t,r_i,0)\)。
-
晚上产生 \(r_i\) 条脏餐巾,连边 \((s,y_i,r_i,0)\),这些脏餐巾会从源点获得并供给以后的餐厅。
-
晚上产生的脏餐巾可以留到次日晚上(但是不洗),连边 \((y_i,y_{i+1},inf,0)\)。
-
白天需要的干净餐巾可以直接购入,费用为 \(p\),连边 \((s,x_i,inf,p)\)。
-
晚上产生的脏餐巾可以经过快洗/慢洗变成干净餐巾留给 \(m/n\) 天后的早上,费用为 \(f/b\) ,连边 \((y_i,x_{i+m},inf,f),(y_i,x_{i+n},inf,b)\)。
跑最小费用最大流。
航空路线问题
把题目要求转化为找两条互不相交的路径,其中起点和终点可以经过两次,其他点最多只经过一次。要求找到路径覆盖顶点数最多的方案。
考虑将经过次数转化为容量限制,覆盖顶点数转化为流量费用。显然要将这些点拆为入点 \(y_i\) 和出点 \(x_i\),连边 \((y_i,x_i,1,1)\) 表示条件限制。特别的,起点和终点的容量要设为 \(2\)。若原图中存在有向边 \((i,j)\) 就连边 \((x_i,y_j,1,0)\) 表示流量能从 \(i\) 走到 \(j\)。跑最大费用最大流。
发现只有在流量为 \(2\) 的时候才会存在一种方案,但由于边的容量限制(实际上去掉这个限制就不会有这个问题),如果存在起点到终点的一条直接路径,那么它的流量会是 \(1\),特判掉这个情况即可。
设跑最大费用最大流所得到的答案为 \(ans\) ,那么最终的答案则是 \(ans-2\) (各去掉起点终点的一次)。递归输出方案,注意遍历完第一条路径要在循环中及时break
,然后再把遍历到的满流边标记成不满流的,下一次就不能再走这条边了。
[SDOI2010]星际竞速
最小路径覆盖可能会很比某些抽象的理解方法更好一些。
模型是一样的,只需要在匹配边上附带上流量费用即可。特别注意的是题目中还要求了如果 \(i\) 成为了某一路径起点则会产生 \(a_i\) 的额外费用。而如果 \(i\) 成为了路径起点,那么 \(y_i\) 所代表的入点边将不会满流,因此要连 \((s,y_i,1,a_i)\) 表示成为路径起点的费用。
然后跑一下最小费用最大流。
80人环游世界
好像还是最小路径覆盖,,,
依然对每个国家拆成入点 \(y_i\) 和出点 \(x_i\),这时发现题目要求的最大匹配次数变了,\(x_i\) 和 \(y_i\) 都可以被匹配 \(V_i\) 次,把匹配次数从 \(1\) 改为 \(V_i\) 即可。其他的连边都跟上一道题差不多。唯一的不同在于,该题限制了人数只能是 \(M\),改一下源点的初始流量就行了。
题目保证了一定会有一种可行方案,直接上最小费用最大流是可行的。
上下界网络流也能做。
[HAOI2010]订货
有些形式的最小费用最大流。但神必题目描述有相当大误导
对于需求可以设点 \(x_i\),连边 \((x_i,t,U_i,0)\)。
然后题目对于当日购入产品的去向进行了这样的描述:
每月月初订购,订购后产品立即到货,进库并供应市场,于当月被售掉则不必付存贮费。
是,是,不用付存贮费固然是好的。但是要进库啊,进库就要占仓库容量的罢?🤔
实际上屁大点儿地方都不占,翻了下讨论区才知道有这个b条件。
所以应该直接连边 \((s,x_i,inf,d_i)\)。再考虑上一个月没卖完的,要有仓库容量的限制和存贮费用,不难想到设点 \(y_i\) 连边 \((y_i,x_i,S,0)\) 表示仓库的限制,再连 \((x_{i-1},y_i,inf,m)\) 表示产品的延期。
最后跑最小费用最大流即可。
[ZJOI2010]网络扩容
不那么形式的最小费用最大流。
第一问是非常裸的最大流,第二问问你扩容 \(k\) 单位流量的费用最小是多少。
考虑到跑完最大流之后的残量网络,如果要扩容那肯定是让满流边扩容,因为让非满流边扩容的话依然会受到满流边的限制。由于我们不知道这条边要扩容多少,所以可以给它的容量设成 \(inf\),费用则设成扩容费用 \(c_i\),其他边的费用统一设为 \(0\)。在源点 \(s\) 处跑流入 \(k\) 流量的最小费用最大流即可。
可能会有 \(k\) 单位流量依然无法流满的情况,这说明原来的非满流边又满流了,再对这些边进行一次一样的操作直到把 \(k\) 单位流量流完即可。每一次跑最小费用最大流都至少扩容 \(1\) 流量,而 \(k\) 最大为 \(10\) ,因此复杂度是正确的。
[TJOI2014]匹配
貌似提出了一个很酷的问题:求所有最大费用完美匹配方案的交集是哪些。
然后发现把交集中任何一个元素删除的话都会导致费用减少。
然后这题就做完了。先跑一次最大费用最大流,枚举所有的满流边,判断删除这条边后费用是否比不删除时有所减少即可。
[CQOI2012]交换棋子
😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜
看上去可能没什么思路。
考虑初始状态到目标状态有什么位置发生变化了,只关注白棋/黑棋就可以,这里关注的是白棋。每一个白棋的交换方案都有办法与其他白棋的位置不交。一个想法是把棋盘上的格子拆成入点 \(y_{i,j}\) 和出点 \(x_{i,j}\) ,连边 \((y_{i,j},x_{i,j},M_{i,j})\),让 \(M_{i,j}\) 充当容量限制。对连通的两个格子 \(a_{i,j}\) 和 \(a_{p,q}\) 连边 \((x_{i,j},y_{p,q},inf,1)\),表示经过这两个格子会导致交换次数的一次增加。如果某个位置初始状态时有白棋子则连 \((s,x_{i,j},1,0)\) ,目标状态下有白棋子则连 \((y_{i,j},t,1,0)\)。跑最小费用最大流,通过判断流量是否为白棋子个数来判断解的有无。
一通操作下来非常的 \(\textrm{nice}\),非常的爽,貌似所有问题都被完美地解决了。
交了一发 \(\textrm{WA} 60\)。
发现棋子初始状态和目标状态的位置都只花一次交换次数,其他都是两次交换次数。
😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜😅多新鲜
然后破大防,看了题解,改了几个地方,过了,又破大防。
首先要把所有格子的容量改成 \(\lfloor\frac{M_{i,j}}{2}\rfloor\) 是肯定的,一个流量当两次用了,而且费用依然是 \(1\) 。考虑初始和目标状态的格子容量该怎么改,发现都加个 \(1\) 就好了,,,稍微注意一下,如果位置不变就只加一次 \(1\) 。
再严谨一些,对于某个初始或者目标状态存在白棋的格子,若 \(M_{i,j}\) 为偶数,发现直接加 \(1\) 的话好像是错的:初始位置在这个格子的白棋需要用到一次交换次数,其他所有的棋子都可能会占用两次的交换次数,所以最多的可流次数为 \(\lfloor\frac{M_{i,j}}{2}\rfloor\),所以这时不需要再加 \(1\);若 \(M_{i,j}\) 为奇数,最多的可流次数为 \(\lceil\frac{M_{i,j}}{2}\rceil\),所以这时需要加 \(1\)。特别的,对于两个状态都存在白棋的格子,\(M_{i,j}\) 为偶数的话也要加 \(1\) ,否则就可能无法匹配这两个位置,或者不关注这类格子也可以。
CF277E Binary Tree on Plane
一眼顶针,鉴定为:啥也看不出来。
考虑将构建二叉树转化为满足父节点与子节点的关系条件。
父节点最多有两个子节点,子节点只有一个父节点。可以将每个点拆成 \(x_i\) 和 \(y_i\) ,连边 \((s,x_i,2,0),(y_i,t,1,0)\) 表示这个点被当成父亲/儿子时的限制。对于可以满足父子关系的节点 \(i,j\) ,连边 \((x_i,y_j,1,dis_{i,j})\) 表示在树中建 \((i,j)\) 的边会产生 \(dis_{i,j}\) 的边权。
容易发现现在跑一下最小费用最大流就能构建出来题目所要求的二叉树了(题目给出的条件不会导致\(i\) 是 \(j\) 的父亲而且 \(j\) 是 \(i\) 的父亲的情况出现)。判断无解只需要判最大流量是否等于 \(n-1\) 即可。
上下界网络流浅看了一下,不想做题了(瘫