网络流模板

 

最大流SAP算法:

  1. 初始弧优化
  2. 分层图优化 
  3. gap优化

初始弧:

dg中记录一个点走到哪条边了,下次只用接着往后枚举。

分层图优化 :

所谓距离标号dis ,就是某个点到汇点的最少的弧的数量dis(一边走一边求),走的时候只走允许弧(dis[i] = dis[j+1] i----->j)

gap优化:

gap[i]数组表示距离标号为i的点有多少个,如果到某一点没有符合距离标号的允许弧,那么需要修改距离标号来找到增广路; 如果重标号使得gap数组中原标号数目变为0,则算法结束。

struct edge
{ll v,fr,d,t; ll c;};//注意d是不变的,c是剩余流量 

ll dfs(ll k,ll flow)
{
	if(k==T)return flow;
	ll have=0;
	for(ll p=cur[k];p;p=e[p].fr)
	if(...)
	{
		ll &v=e[p].v,&c=e[p].c;
		if(dis[k] -1 == dis[v] && c)
		{
			cur[k] = p;
			ll now = dfs(v, min(flow - have,c));
			c-= now;
			e[p^1].c+=now;
			have+=now;
			if(have == flow)return flow;
		}
	}	
	cur[k] = tail[k];
	
	if(!(--gap[dis[k]])) dis[S]=T;
	gap[++dis[k]]++;
	
	return have;
}

ll network_flow()
{
	mem(gap,0);
	mem(dis,0);
	for(i=0;i<=T;i++)cur[i] = tail[i];
        int ans=0;
	while(dis[S] < T) ans+=dfs(S,INF);
	return ans;
}

详细地:


在dfs中,有两个形参k,flow分别表示当前流到的点和走到目前的可行流量。

1.如果k==T即走到汇点返回当前这一条增广路的可行流量flow。

2.如果还没到达汇点,尝试尽可能流出这flow的流量,我们用have记录流出的流量。
    枚举出边,设出边到达的端点为v ,这条边的剩余流量c。
    若这是一条可行边(dis[k]  == dis[v] + 1)且剩余流量大于0 ,则尝试流这条边。初始弧更新。
计算通过这条边可以留出的流量。
已知flow那么多的流量还剩下flow - have ,那么显然now = min(flow - have , c) 。
然后更新这条边的剩余流量 , 这条边的反向边加上now,have加上now。
have == flow没东西可以流了 , return flow(全部流完)。

3.还有剩下的流量,尝试将距离标号加1创造机会。
初始弧还原。
如果更新后原标号的个数为0了,出现断层,程序结束。否则更新。

4.看看程序是否结束了(dis[S] == T时结束 , 因为此时已经试完了所有情况),没结束回到dfs 。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值