https://www.cnblogs.com/victorique/p/8560656.html
强烈推荐
昨天看到这种建模方法懵逼,事实上只不过是我做的网络流的题太少了而已(一共就做了3道题吧。。。)
事实上最大权闭合子图对应一个最小割因此就对应着最大流。最大权闭合子图的权值等于所有正权点之和减去最小割。
. 最小割一定是简单割
简单割指得是:割(S,T)中每一条割边都与s或者t关联,这样的割叫做简单割。
因为在图中将所有与s相连的点放入割集就可以得到一个割,且这个割不为正无穷。而最小割一定小于等于这个割,所以最小割一定不包含无穷大的边。因此最小割一定一个简单割
简单割一定和一个闭合子图对应
闭合子图V和源点s构成S集,其余点和汇点t构成T集。
首先证明闭合子图是简单割:若闭合子图对应的割(S,T)不是简单割,则存在一条边(u,v),u∈S,v∈T,且c(u,v)=∞。说明u的后续节点v不在S中,产生矛盾。
接着证明简单割是闭合子图:对于V中任意一个点u,u∈S。u的任意一条出边c(u,v)=∞,不会在简单割的割边集中,因此v不属于T,v∈S。所以V的所有点均在S中,因此S-s是闭合子图。
由上面两个引理可以知道,最小割也对应了一个闭合子图,接下来证明最小割就是最大权的闭合子图。
首先有割的容量C(S,T)=T中所有正权点的权值之和+S中所有负权点的权值绝对值之和。
闭合子图的权值W=S中所有正权点的权值之和-S中所有负权点的权值绝对值之和。
则有C(S,T)+W=T中所有正权点的权值之和+S中所有正权点的权值之和=所有正权点的权值之和。
所以W=所有正权点的权值之和-C(S,T)
由于所有正权点的权值之和是一个定值,那么割的容量越小,W也就越大。因此当C(S,T)取最小割时,W也就达到了最大权。
小Ho:我懂了,因为最小割也对应了一个闭合子图,因此它是可以被取得的,W也才能够到达最大权值。
小Hi:没错,这就是前面两条引理的作用。
小Ho:那么最小割的求解就还是用最大流来完成好了!
小Hi:嗯,那就交给你了。
看上去挺对的(网络流除非水平很高否则算法基本上都是感性理解吧)。
然后补充一道sb题。
[NOI2006]最大获利
题目描述
新的技术正冲击着手机通讯市场,对于各大运营商来说,这既是机遇,更是挑战。THU 集团旗下的 CS&T 通讯公司在新一代通讯技术血战的前夜,需要做太多的准备工作,仅就站址选择一项,就需要完成前期市场研究、站址勘测、最优化等项目。
在前期市场调查和站址勘测之后,公司得到了一共 N 个可以作为通讯信号中转站的地址,而由于这些地址的地理位置差异,在不同的地方建造通讯中转站需要投入的成本也是不一样的,所幸在前期调查之后这些都是已知数据:建立第 i个通讯中转站需要的成本为 P_iP**i (1≤i≤N)。
另外公司调查得出了所有期望中的用户群,一共 M 个。关于第 i 个用户群的信息概括为 A_iA**i , B_iB**i 和 C_iC**i :这些用户会使用中转站 A i 和中转站 B i 进行通讯,公司可以获益 C_iC**i 。(1≤i≤M, 1≤A_iA**i , B_iB**i ≤N)
THU 集团的 CS&T 公司可以有选择的建立一些中转站(投入成本),为一些用户提供服务并获得收益(获益之和)。那么如何选择最终建立的中转站才能让公司的净获利最大呢?(净获利 = 获益之和 – 投入成本之和)
输入输出格式
输入格式:
输入文件中第一行有两个正整数 N 和 M 。
第二行中有 N 个整数描述每一个通讯中转站的建立成本,依次为 P_1 , P_2 , …,P_NP1,P2,…,P**N 。
以下 M 行,第(i + 2)行的三个数 A_i , B_iA**i,B**i 和 C_iC**i 描述第 i 个用户群的信息。
所有变量的含义可以参见题目描述。
输出格式:
你的程序只要向输出文件输出一个整数,表示公司可以得到的最大净获利。
输入输出样例
输入样例#1:
1 | 5 5 |
输出样例#1:
1 | 4 |
说明
样例:选择建立 1、2、3 号中转站,则需要投入成本 6,获利为 10,因此得到最大收益 4。
100%的数据中:$N≤5 000,M≤50 000,0≤C_i≤100,0≤P_i ≤100。$
题解
我们把每个人看成是一张图一条边(废话),每个站看成一张图的点。
然后求这张图的最大闭合子图即最小割即最大流。
答案就是总收益(这道题就是所有的用户收益)-最小割。
具体方法前面讲了。
1 | // luogu-judger-enable-o2 |
[AHOI2009]最小割
题目描述
$A,B$两个国家正在交战,其中A国的物资运输网中有$N$个中转站,$M$条单向道路。设其中第$i (1≤i≤M)$条道路连接了$v_i,u_i$两个中转站,那么中转站$v_i$可以通过该道路到达$u_i$中转站,如果切断这条道路,需要代价$c_i$
现在B国想找出一个路径切断方案,使中转站$s$不能到达中转站$t$,并且切断路径的代价之和最小。
小可可一眼就看出,这是一个求最小割的问题。但爱思考的小可可并不局限于此。现在他对每条单向道路提出两个问题:
- 问题一:是否存在一个最小代价路径切断方案,其中该道路被切断?
- 问题二:是否对任何一个最小代价路径切断方案,都有该道路被切断?
现在请你回答这两个问题。
输入输出格式
输入格式:
第一行有44个正整数,依次为$N,M,s,t$
第22行到第(M+1)(M+1)行每行33个正整数$v,u,c$,表示vv中转站到uu中转站之间有单向道路相连,单向道路的起点是vv, 终点是$u$,切断它的代价是$c(1≤c≤100000)$
注意:两个中转站之间可能有多条道路直接相连。 同一行相邻两数之间可能有一个或多个空格。
输出格式:
对每条单向边,按输入顺序,依次输出一行,包含两个非00即11的整数,分别表示对问题一和问题二的回答(其中输出11表示是,输出00表示否)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输入输出样例
输入样例#1:
1 | 6 7 1 6 |
输出样例#1:
1 | 1 0 |
说明
设第(i+1)(i+1)行输入的边为ii号边,那么\{1,2\},\{6,7\},\{2,4,6\}{1,2},{6,7},{2,4,6}是仅有的三个最小代价切割方案。它们的并是\{1,2,4,6,7\}{1,2,4,6,7},交是 \{\varnothing \}{∅} 。
测试数据规模如下表所示
数据编号 | N | M | 数据编号 | N | M |
---|---|---|---|---|---|
1 | 10 | 50 | 6 | 1000 | 20000 |
2 | 20 | 200 | 7 | 1000 | 40000 |
3 | 200 | 2000 | 8 | 2000 | 50000 |
4 | 200 | 2000 | 9 | 3000 | 60000 |
5 | 1000 | 20000 | 10 | 4000 | 60000 |
题解
让你求最小割的可行边与必经边的板子。。。
04年就有这个题的明确解决方法了吧。。。
最小割的必经边求出任意最小割后肯定是满流。并且S能到一端点,另一端点能到T。必须边的另一种理解是扩大容量后能增大最大流的边
证明暂时略,具体求法就是从S开始DFS,T开始反向DFS,标记到达的点,然后枚举满流边。可以直接Tarjan求出SCC后判断S与一端点,T与另一端点是否在一个SCC中,满足即可
这道题的第二问就解决了。
最小割的可行边$E$也必须是满流(否则这条边不是瓶颈,最小割应该是那条满流的边) , 同时残余网络中$u$到$v$不应该存在路径,否则由于这条边$E$是瓶颈,那么源点到它的端点和它的端点到汇点构成增广路。
第一问也解决了。
然后半天调不出来,数组不知道为什么非得开三倍,Dinic慢的可怕,Tarjan直接卡死。。。
调了半天调出数组开小。
然而还有一个蜜汁错误:我网络流加了一个优化:
1 | for(int k ; (int)q.size() ; q.pop()) |
在这个分层中注释掉的那句话,就是最后的bug
我确实不知道为什么,凭直觉定位了那个错误注释了就AC了。。。
LOJ+BZOJDATA是好东西,大大提高做题的效率。
Code:
1 |
|
最长不下降子序列1
2for(1...n)
f[std::upper_bound(f+1,f+ans+1,a[i])-f]=a[i];
最长不上升子序列1
2
3f[1]=a[1],ans=1;
for(2...n)
f[std::upper_bound(f+1,f+ans+1,a[i],std::greater<int>())-f]=a[i];
最长上升子序列1
2for(1...n)
f[std::lower_bound(f+1,f+ans+1,a[i])-f]=a[i];
最长下降子序列1
2
3f[1]=a[1],ans=1;
for(2...n)
f[std::lower_bound(f+1,f+ans+1,a[i],std::greater<int>())-f]=a[i];
只有这点东西是因为我去补多项式笔记和做了个睿智的校内测试。
说是关于推荐名额的考试。
然后发了一个两道题的文档,3个小时?第一道傻逼模拟全场切,第二道是暴力AC玄学题。
然后我发现我为了优化搜无序点对然后乘$2^{k-1}$错了。
所以那些有爆搜分的就比我高了。
所以可以安心滚粗了嘻嘻嘻。
睿智测试。