网络流

最大流/最小割

  • 增量建图
  • 最大权闭合子图
  • 二分检验
  • 最小割一定要找全矛盾关系,如文理分科 选文选理,同选文同选理矛盾
  • 最大流的一个单位流量经过的点代表的是这个点的特征
  • 最小割就是如果能从S到T,那么这条路就是非法的,如果单个点矛盾关系不是很多,可以建立每个点和所有矛盾关系之间的
  • 先处理好局部的关系,再拓展到全局,如:employ人员雇佣 对于两点a,b之间存在 选a选b 减去$c_a,c_b$ 选a,b其中一个 减$E_{a,b}*2,c_a/c_b$,不选a,b减$E_{a,b}$
  • 然后可以发现,如果不选i,那么所有的$E_{i,j}$都得不到,所以可以连边表示$sum_i$与$c_i$的取舍关系,发现只选一个还要多减,再连边$a->b,b->a$
  • 这样如果两条与源点相连的边被割掉合法,两条与汇点割掉也合法,当只有一个割掉的时候,S与未选点之间还是有流量,流向所有的已选点,满足题意。
 1 inline bool bfs()
 2 {
 3     memset(d,0,sizeof d);
 4     d[q[h=t=0]=S]=1;hd[S]=head[S];
 5     while(h<=t)
 6     {
 7         int x=q[h++];
 8         for(int i=head[x],y;i;i=nxt[i])
 9         {
10             if(!val[i]||d[y=to[i]]) continue;
11             d[q[++t]=y]=d[x]+1;hd[y]=head[y];
12             if(y==T) return 1;
13         }
14     }
15     return 0;
16 }
17 int dfs(int x,int f)
18 {
19     if(!f||x==T) return f;
20     int las=f;
21     for(int &i=hd[x],y;i;i=nxt[i])
22     {
23         if(!val[i]||d[y=to[i]]!=d[x]+1) continue;
24         int t=dfs(y,min(las,val[i]));
25         if(t) val[i]-=t,val[i^1]+=t,las-=t;
26         else d[y]=0;
27         if(!las) return f;
28     }
29     return f-las;
30 }
dinic最大流

费用流

  • 费用流还是满足一个单位流量的特征
  • 一般最大流来保证满足题设,费用是最优化花费
  • 灵活转化题意。
  • 有些题要求每个点均遍历一遍,可以转化为每个点的入度出度均为1,可以想到拆点,把一个点拆成入点和出点,限流最大流量为n,直接最小费用最大流
  • 有些题要求一定要跑满,可以把你想跑满的边的边权设为-inf,最后再加上,这样保证跑想跑的边一定比其他的费用小,可以说是skyh对网络流的深刻理解。
  • 对于有一些问题子集分化不明显,考虑利用条件把其转化为二分图。如:数字配对,千钧一发
  • 有一些简单的优化 如:动态开点,不要思维僵化只想增量枚举!!!费用流不能跑在残量网络上跑。
  • 一类套路:配对问题考虑利用特殊性质转化为二分图
  • 网格图优先想黑白染色!!!!

上下界网络流

  • 其实就是想办法把下届的条件去掉
  • 无源汇可行流是基础,先构造一个不满足流量守恒,跑满下届,再跑一个附加流,建虚拟源汇点,调整每个点的出入流量,跑就完了。
  • 对于有源汇的,因为S和T不满足流量守恒,建一条从T到S的INF边就好了
  • 最大流和最小流都是通过在残量网络上跑来实现的。
  • 如果虚拟源汇点跑满了,说明存在合法解,此时的残量网络是一个合法解,但是不一定是我们想要的。
原文地址:https://www.cnblogs.com/hzoi-kx/p/11961230.html