网络流24题

题目链接:
<最大流有FF、EK、Dinic算法,最小费用流有SPFA、DIjkstra求解算法等,网络流在于建模,在此不在贴出代码>

P2756 飞行员配对方案问题

  • 二分图最大匹配(匈牙利算法),看着模板一顿乱敲即可。

P4016 负载平衡问题

  • 最小费用流
  • 建模:源点s=0,汇点t=n+1,平均值ave(对于样例为12)
    1. 源点s向节点i(i的值s[i]>平均值ave)连边,花费0,容量s[i]-ave。
    2. 节点i(i的值s[i]>平均值ave)向节点j(j的值s[j]<平均值ave)连边,花费为节点i和j的顺逆中的最短距离,容量s[i]-ave。
    3. 节点j(j的值s[j]<平均值ave)向汇点连边,花费0,容量ave-s[j]。

P1251 餐巾计划问题

  • 最小费用流
  • 建模:源点s,汇点t,第i天为节点i。add_edge(from,to,cost,cap)。
    1. 对于节点i,每天都可以直接购买今天所需的餐巾数,连边:add_edge(s,i,p,num[i]) 。每天都需要num[i]数量的餐巾数,即保证每天向汇点t流入num[i]流量,连边:add_edge(i,t,0,num[i])。
    2. 节点i的餐巾可以经过快洗/慢洗送给节点i+m/i+n使用。这就表明了:
      ①从节点i流向节点i+m/i+n的容量必为num[i]。
      ②由于从源点s流向节点i的容量为num[i],而节点i流向节点i+m/i+n容量为num[i],流向汇点t的容量也为num[i],不满足一定可以向节点i+m/i+n流容量num[i]。
      所以,对节点i进行拆点,拆为i和i+N,拆点之后直接从汇点s向i+N连边,不经过节点i。
    3. 源点s=0,汇点t=2*N+1。
      源点s向节点i+n连边,容量为num[i],即:add_edge(s,i+N,0,num[i]),保证了条件2。
      同时节点i的餐巾可以经过快洗/慢洗送给节点i+m/i+n使用,分别连边:add_edge(i+N,i+m,f,inf);add_edge(i+N,i+n,s,inf)。
    4. 节点i的餐巾只需送给第i+m/i+n个节点就好,然后分别在节点之间连边,add_edge(i,i+1,0,inf);表明今天剩余的餐巾可以留到下一天用。
// 建模代码:
int st=0,ed=2*N+1;
for(int i=1;i<=N;i++){
	add_edge(st,i,p,num[i]);
	add_edge(i,ed,0,num[i]);
	add_edge(st,N+i,0,num[i]);
	if(i+1<=N)add_edge(i,i+1,0,inf);
	if(i+m<=N)add_edge(N+i,i+m,f,inf);
	if(i+n<=N)add_edge(N+i,i+n,s,inf); 
}
printf("%lld\n",min_cost_flow(st,ed));

P2761 软件补丁问题

  • 最短路(说好的网络流24题呐!),状态用二进制压缩一下。
    对于样例n=3,起点状态:111 终点为:000
    对于状态u可以依次判断是否和1~m个补丁相容,进而进行状态转移。

P2762 太空飞行计划问题

  • 感谢博主hiho问题的幽默阐述和博主Dilthey的结论证明,在此万分感谢~
  • 最后一次BFS建立分层图中level[i]>0的点就是所求答案,因为从源点s出发的所能达到的点都在最大权闭合子图里,证明见Dilthey博客!

P3254 圆桌问题

  • 最大流思路:二分图多重匹配,按照最大流建模即可。
  • 贪心思路:依次把各单位分配给餐桌座位余量最大的餐桌,对于第一个单位的分配,各餐桌余量为餐桌容量;第二个单位的分配,先对各餐桌按座位余量sort一下,按从大到小给第二个单位分配,依次类推,中间不能分的时候,说明题目无解。贪心证明:不会~

P2763 试题库问题

  • <思路同上题>最大流:源点s=0,汇点t=k+n+1。
  • 类型节点1~k,题目节点 k+1~k+n。
  • 源点到类型节点连边,容量为每个类型所需数;类型和相对应的题目连边,容量为1;题目和汇点连边,容量为1,跑一边最大流即可出锅。

P2770 航空路线问题

题意:即是求1~n的两条不相交路径,使得路径经过的点总数最多。
由于航线不能重叠,所以每个点只能经过一次(最后一个点和第一个点最多两次)。

  • 最大费用最大流:源点s=1,汇点t=n+n。
  1. 每个点只能经过一次,即顶点有流量限制,这时候要拆点,控制流出流量为1,把节点i拆为节点i和节点i+n。
  2. 源点和汇点拆点(来回可经过两次,容量为2):add(i,i+n,0,2)。 其它点(只能经过一次,容量为1):add_edge(i,i+n,0,1)。
  3. 航线连边,西边城市i向东边城市j连边:add_edge(i+n,j,1,1)。航线连边,西边城市i向东边城市j连边:add_edge(i+n,j,1,1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值