2018年2月1日训练日记

昨天晚上的cf。。。打的非常惨烈。。。只出了3题。。第三题还被hack了一次。。。好歹最后过了。。。D题没想到dp。。。TLE on test 15。。。赛后看了一眼Q神代码。。。把自己的代码改改一下就过了。。。(sad,为什么没想到dp呢)最后rank2300+,掉了好多分。。。明天还有比赛。。。希望不会太惨。。。

图论-网络流:

常常用floyd求出最短路当做费用...然后最小费用最大流求最小总距离,注意有的题目要用long long

由于一个点至多经过k次。那么就想到了用拆点来限制点的经过次数。

有些题有某一种情况状态数比较小(<=15)注意状态是否可以压缩

注意某些题起点s=t终点的情况或者s直接连t要特判

求二分图的最小权匹配==求最小费用最大流

遇到从s出发到t再回来不经过重复的题:拆点,源点、汇点边权为2,其他为1,表示只能走一次。i<<1和i<<1|1

给二维点标号:i*n+j(0<i<n,0<j<n),注意n方-1=n*(n-1)+n-1。第一个点为0,最后一个点为n方-1。

有的问题由于点或边比较多而超时,要注意枚举每种物品或压缩状态。

有的题目求偏移量:加偏移量就是,由于边数最多10^5,那么就把偏移量设置为比其大的就行了(如2*10^5)注意的是加了偏移量后,流量会超int,那么与流量有关的变量都要设置为long long,特别注意的是流量初始的最大值,也要相应的扩大。(inf变为inf*inf)

判断割边集是否唯一先跑最大流求最小割..然后从起点开始dfs..对能到达的点标记为1(边的容量非空才能走)...再从终点开始dfs...对能到达的点标记为2(对应的边容量非空才能走)..然后扫描所有的边..若一条边已经满流了..但是其起点或者终点没有被标记到.则说明最小割边集不唯一

前天写到:求最大流等价于求最小割也等价于求最大权闭合图。今天找到了例题:

题意:现在给出在一些N位置建造基站的费用..基站建立后就可以与其他的基站进行通信。而现在有M个用户..每个人要求某两点要能通信(这两个位置上建造了基站)..并且其会支付一些费用..问最多能赚多少费用....
题解:所谓闭合子图是指在一个有向图中存在的这么一个子图,若有边(u,v)并且u属于闭合子图中那么v就必须在闭合图中...可以理解为(u,v)为一个必要关系(有了u就必须要有v)..而最大权闭合子图.就是每个点有权值.点权之和最大的就是最大权闭合子图...
而本题就是这么个意思..有M+N个点.前M个点代表的是用户..其点权为满足该用户的必要条件这个用户会支付的钱..而后N个代表的是在N个位置建造基站..点权为其代价..所有的用户向其所要求的基站做边..代表要选择该用户就必须选择其指向的基站...现在问题已经完全抽象成最大权闭合子图的模型了...
下面就是如何来求解这个模型的值:
1、超级源点向所有的用户做边,容量为其能支付的费用,并且把所有的收益加起来记为sum
2、每个用户向其所要求的基站做边,容量为无穷大。
3、每个基站向超级汇点做边,容量为建造这个基站所需的费用。
4、sum-MaxFlow(超级源点->超级汇点) 就是答案

注意:裁掉的员工人数(建造的基站)就是以割为界,靠近源点一边的点数。

经典例题:

题意: 有一个无向图..农夫从1号点出发..要到达N号点..然后回到1号点..来回不能走相同的路径..问最短的距离是多少。
题解:超级源点向1号点做边..容量为2,n号点向超级汇点做边..容量为2,然后就是根据给的边给两个点做边..
注意:最小费用最大流在做无向图边时不像最大流时那样.直接把那容量为0的反向边容量改成相同的..而是要扎扎实实的加两次..因为费用这个变量的存在。

题意: 给了N个开区间..每个区间有权值..限定不能任何一个点被K个区间覆盖..问满足条件的选择区间..使得权值之和最大为多少
题解:将所有的点存下来排个序..也就是离散化..那么一共2n个点..记为m,令s为超级源点..e为超级汇点..做边s->1->2->3...->m-1->m->e..每条边容量为K..费用为0...再对于N个区间,其起点往终点做边..容量为1..权值为其权值的相反数..然后跑最小费用最大流..答案就是最小费用的相反数
算法正确性证明:如果两个区间没有交集,那么代表它们的边可以出现在同一增广路上,这一点显然。否则,它们就在不同的增广路上。每一个区间对应的边的容量都是1,这样,最后的流量就是被选出的两两有交集的区间的数量。受到(0,1,k,0)这条边的容量限制,这个值刚好不大于k.区间的权都是正的,因此选取的区间多多益善,所以流量必然最大。
(对于每次选取的增广路中总存在一个区间,在每次增广所得区间都与这个区间有交集)

题意: 国王决定给你一些城市让你选择...首都是1号点..国王要求不能从1号点出发走到选择的城市..可以花一定代价去掉路...选择每个城市可以获得一定的分数..问可以获得的最大分数..以及要去掉的边的序号
题解: 对于所有的边..起点往终点做边..容量为其去掉的代价...所有能选的城市与超级汇点做边..容量为选其能获得的分数..将所有可能获得的分数加起来减去构图的最大流(最小割)...就是答案
题目还要求输出去掉了哪些边..那么从起点开始标号..如果容量为0就不能沿着这条边往下走..然后扫描所有的边..若其起点被标记了.终点未被标记..则该边是最小割中的割边
总结:这是一类比较典型的最小割模型...特点是要以什么代价选择什么可以获得一些分数..那么将可以获得的分数加起来..然后把代价和获得的分数都做边...假设跑出的最小割有获得分数的..那么总分数在减的时候相当于不选它

找割边:(POJ 2125 - Destroying The Graph 构图最小割)

void dfs(int x)  
      {  
              mark[x]=true;  
              for (int k=head[x];k;k=edge[k].next)  
                  if (!mark[edge[k].v] && edge[k].c) dfs(edge[k].v);  
      }  
      void getans(int s,int e,int &num,int *ans)  
      {  
              num=0;  
              memset(mark,false,sizeof(mark));  
              dfs(s);  
              for (int i=2;i<=ne;i+=2) // 注意扫描的是建造的边.不要扫描建造的反向边  
                if (mark[edge[i].u] && !mark[edge[i].v] && !edge[i].c)  
                  if (edge[i].u==s) ans[++num]=edge[i].v;  
                              else  ans[++num]=edge[i].u;  
      }
以上知识内容根据大佬博客总结而来。。。(by zzyzzy12)看了他的总共68道网络流的题目收获还是蛮多的。。感谢大佬

现在感觉网络流的题有那么一些套路了...

加油。






阅读更多
换一批

没有更多推荐了,返回首页