最短路
(;)
Problem
(;)
无向图,走(d)步能否到达,每个点拆成奇偶两个点考虑
(但好像拆点比直接记0/1慢)
次短路
(;)
正常是考虑到每个点的最短和次短路(f,g)
尝试互相去转移。分类讨论好麻烦啊
不妨跑两遍,(g)的更新初始用(f)来算,现在相当于把所有(f)对(g)的影响算好了。
然后再只考虑(g)对(g)的影响,就在跑一遍最短路(大于(f)的前提下)
同余最短路
(;)
给定(a_1,a_2,...,a_n),问有多少个(B),使得(a_1x_1+a_2x_2+...+a_nb_n=B)非负整数解
我们不妨把(a_1)拿出来(其实任意一个都行),把所有的B按模(a_i)的余数分开考虑
因为只要(ka_1+x)被凑出来了,那么所有((k+1)a_1+x,...)的数都可以被凑出来,相当于模(a_i)分到同一组内的数都可以由其中最小的那一个转移而来
考虑求这个最小的数,也就是求最小的(k)
一个(a_i),相当于建一条(x)->((x+a_i)\%a_1)的边,对于那种顶到右边界绕到左边的边权应该为1
复杂度:(O(na_ilog a_i))
优化建边方式
映射到坐标轴上
(;)
两点距离为横坐标差和纵坐标差的较小值
发现把点的坐标映射到(x)和(y)轴上,那么我实际上要让它映射到的两个点看成同一个点,只不过是两种不同的转移方式
那么显然只需要让在(x)轴上相邻的点连边,一个点映射的两个点间连一条边权为0的边
(;)
或是在坐标轴上跳时,和距离有关,不妨从(i)向(i-1)连边
数据结构优化
(;)
向一段区间内的点都连边
正常是开一个中继点,这里可以采取线段树的方式。
那么向线段树的对应节点连边
或是分块,对于(l)个块到(r)个块,建一个点,这样总共有(O(n))个点
零散块直接在坐标轴上维护前缀和后缀的辅助点
bzoj4144
(;)
这道题好妙
首先肯定要求出连接加油站的生成树(因为路径可以抽象经过一段段的路径,走到一些加油站)
然后我们要防止在加油站之间死掉,也就是让这颗生成树上一条路径上最大的边最短(显然就是最小生成树)
那么那些加油站之间可能连边呢?
考虑原图的边,只有一条边所连的两个点属于的集合不同,那么这两个集合之间的加油站才可能连边。
(这个证明大概就是中间如果隔着一个加油站,去那里加油会更优
网络流
卖猪问题
(;)
最开始比较好想的是分层图。
按照顾客来的顺序去分层。
但这样发现点数和边数会比较多,考虑优化
一种是建图的优化
1.多条inf的边串联或并联,那么之间变成一条
2.可能有一条有限制的边和一条inf的边并联,直接改成一条inf的边
3.如果发现有两两加边的情况,考虑在中间加个中继点
还有另外一种建图的方式
如果两个人之间有交集,发现前面的人可以给后面的人预支一些猪。
其实相当于简化了过程。原先是人——>猪圈——>人,现在直接从人——>人
但其实向下一个打开猪圈的人连边会更好(其实有点像把这个人作为中继点)
SGU 326
(;)
贪心让1赢得尽可能多比较显然
对于两队进行比赛的题目(往往就可以把比赛看成一个汇点(当然不是总汇点),向两队连边),所以只会把胜利分配给两队的其中一个
虽然网络流无法判断是否把容量撑爆,但是可以看与源点相连的边是否满了即可
POJ2699
(;)
这里不能把一个点拆成输赢了(因为只知道它赢了多少场不能判断它是否是king)
发现n很小,就要尝试一些暴力的思路,比如说枚举,状压之类的。
这里有一些特殊的性质,只用选分数最高的k个。
因为我们要让得分高的先赢的多,这样感觉会更容易满足。
还是刚刚的建图方式
SGU 438
(;)
往往有一些网络流的题,会有一些像dp的阶段。
比如:时间,顾客的人数。
这种往往都是针对的全局的状态(即每个点的属性都会变成这样),像时间就是每个点都来到了这个时间。
这道题,每个点都有限制,能不能按这个限制分层呢?显然不好做,因为每个点的限制是不一样的。
但如果不分层呢?因为这道题中强调了时间的概念(即让时间尽可能短),而如果只是一层感觉不太好记录现在已经过了多长时间了)
所以要把整体按时间分层。而ci的限制就在分层图中的每一层中拆点。(这样满足了"同时"的限制)
一种简单的想法是,二分时间T,判断能否满流,但时间有些无法接受。
还有一种比较好的思路是,因为我要最小化最大时间,所以只要有一个人到了比较大的时间,就会是答案不优。
我们于是考虑费用,让T+1的费用至少是T的费用的100倍,但费用流也太慢
所以考虑逐层加点,也就是动态网络流的过程,在残量网络上继续增广,这样只相当于改变了增广的顺序,对于dinic的复杂度还是没有影响的
SPOJ 962
(;)
要求A到B,B再到C,且中途不能重复经过同一个点。
是不是想到了传纸条那道题~
所以我们只需要找两条路径,分别以A,C为起点,终点是B,要求不能有重叠的地方,那么显然可以拆点。
闲的没事想了一下如果要经过A,B,C,D,E,F....这种题怎么做,发现不会。貌似不大能扩展
HDU 5639
(;)
太神仙了这道题。
乍一看,每次只能删去一颗基环树森林?什么玩意。
但基环树有非常好的性质:即每个点只有一条出边。(这里我们把它看成内向树)
所以每次,假如每个点唯一匹配了一条边,然后把这些边删去,一定能满足条件。
(感觉又是一个映射的思路?其实也不大像,但可以这么类比)
那么这若干轮,每个点可能会匹配到若干个点。
假如我们已经确定了每个点所匹配的边的集合,那么显然最多的那个就是答案。
让最大的最小,显然就可以二分(或是不断扩容),感觉后者更好一些,和比赛分配胜利一样的建图方式。
HDU 1956
(;)
给定有向边和无向边,问:是否能给无向边分配方向,使得图中包含欧拉回路。
又是经典题
先给无向图随机分配方向,考虑去动态调整
发现(C)=出度-入度是偶数,是负数的就要从源点向它连边,反之则向汇点连边。
然后将原图所有无向边反向建图,容量为1
这样考虑从(S->x),每流大小为1的流,即:把这条流所流的路径上的边都反向过来,且中途经过的点的(C)不会边,且让终点和起点,分别想它们各自的目标靠近了1
POJ2396
(;)
知道每行每列的和,各自整数的取值范围
构造这样的矩阵
考虑从S向行的关键点连边,T向列的关键点,每个点都向它所属的两个关键点连边。
但此时有上下界的限制,于是考虑上下界网络流。
与普通的网络流只多了下界的限制,考虑怎么去除下界,剩余的就和正常的一样了。
考虑先给他分配好了,那么现在会出现问题,即:流量不平衡。
好,对于入>出,说明出去的边流量小了,于是考虑用源点向它加条边,那么就会流到出边上。
否则,用汇点向这个点连边,那么入边的流量就不得不多了。
BZOJ 1143
(;)
DAG,选最大的点集,使得两两不到达。
DAG中,最长反链=最小链覆盖(这里是可以相交的)
所以还得Floyd传递闭包(这玩意挺好用的,能弄出每对点的联通性)
至于判断一组解,有一个比较好的思路。
已知最优解是(k)个点
我们暴力判断选出一个点之后,剩下的的点能否选出(k-1)个点就行了,且选完之后要把所有和这个点有偏序关系的点删去
再在剩下的点所构成的若干个联通快上做,(k-2,k-3...)这样一定就能找到一组解了
最小割
切糕模型
(;)
这个东西非常的牛逼,可以扩展到很多问题。
P3227:发现两个相邻位置的高度不能超过D,对应的是一个矛盾的关系。
在建模的时候,我需要根据题目的需求来使发生矛盾后,是会付出一定的代价,还是根本不可行
假如说,我们把原问题的中一个东西的代价看作图上的一条边。
而切断这条边,看作选了这个东西,并付出代价(注意这里边所代表只能是代价,而不能是价值),因为没有最大割这个东西
而我们通过一系列高超的建模,又能使每一种方案都能且必须把这张图切断,就可以转化为最小割问题。
对于切糕模型,基本对于两者矛盾的关系,需要构造出两条链,而选了一个A链的前缀和B链的后缀中的点,会导致产生矛盾。
于是在两条链之间竖着加一条边,容量为(INF)或是(c),按题目而定。
这道题就需要从((i,j,k))向((i,j,k+D))去构造一条容量为(INF)的边
BZOJ1934
(;)
每个小朋友有两种选择,每种选择可能对应着一定的代价,就不妨把每种选择看成一条边,尝试去割。
与原意愿不符为1,否则为0
且发现两个好朋友如果选择不同(这里就变成了一段前缀和后缀),当然要付出1的代价,连边。
POJ2987
(;)
上司被裁,员工也被裁,感觉可以建出上司->员工的边。
但这样不好。
套用切糕模型,有裁或不裁两种。
和上题一样。但有两点不同
1.中间的边是(INF),因为题目是不允许
2.这里是价值而不是收益,所以先把会贡献正收益的选上,那么如果裁掉他,相对那么会挣0的钱,否则就要退还,即付出代价。
对于负收益的,显然可以直接套用。
感觉这样是先算后退的样子
HDU1569
(;)
每个格子选或不选,但这里是两个前缀的矛盾,所以直接黑白染色,对于黑色把选放在前缀,白色把选放在后缀,然后先算后退就可以
BZOJ1001
(;)
臭名昭著(bushi)的狼抓兔子。
发现把一个正方形的分成的两个三角看作2个点,然后把图上跨过一条边的点对连边。
那么可以把一个割,看作从(S)到(T)的任意一条路径,那么求最短路即可。
好像是什么转对偶图后,原图最小割=对偶图最短路
BZOJ1070
(;)
按维修人员考虑,显然倒数第(k)个车会贡献(k)倍的代价
那么直接费用流解决(这道题有一些提前算贡献的思路)
Vijos1891
(;)
一道按照费用流本质出的题,目前还不会,挖个坑