ISAP模板(网络流模板)

 附上学习地址:

https://www.luogu.org/blog/ONE-PIECE/jiu-ji-di-zui-tai-liu-suan-fa-isap-yu-hlpp

ISAP过不掉的题:

https://loj.ac/problem/127

const int maxn = 1e4 + 3000;
const int maxm = 4e5 + 10;
const int inf = 1 << 30;
int s, t;
int n, m; 
int maxflow;
int cnt, head[maxn], curedge[maxn];
int depth[maxn], gap[maxn];
//depth[i]表示节点i的深度,gap[i]表示深度为i的点的数量 
struct Node {
    int v;
    int c;
    int nex;
} edge[maxm];
void init(){
	cnt = 0;
	 memset(head, -1, sizeof(head)); 
} 
inline void addedge(int u, int v, int c) {
    //正向建边
    edge[cnt] = { v, c, head[u] };
    head[u] = cnt++;
    //反向建边
    edge[cnt] = { u, 0, head[v] };
    head[v] = cnt++;
}
void bfs() {	//从t到s进行分层 
    memset(depth, -1, sizeof(depth));
    memset(gap, 0, sizeof(gap));
    depth[t] = 0;
    gap[0] = 1;
    queue<int> que;
    que.push(t);
    while (!que.empty()) {
        int u = que.front();
        que.pop();
        //遍历u 的所有出边 
        for (int i = head[u]; i != -1; i = edge[i].nex) {
            int v = edge[i].v;
            if (depth[v] != -1)	//已经被分过层 
                continue;
            que.push(v);
            depth[v] = depth[u] + 1;	// v是u 的下一层 
            gap[depth[v]]++;	//深度为depth[v]的点的数量+1 
        }
    }
    return;
}
int dfs(int u, int flow) {
    if (u == t) { 	// 可以到达t 
        maxflow += flow;
        return flow;
    }
    int used = 0;  //用来表示这个点的流量用了多少
    for (int &i = curedge[u]; i != -1; i = edge[i].nex) {
        int v = edge[i].v;
        if (edge[i].c && depth[v] + 1 == depth[u]) {
            int mi = dfs(v, min(edge[i].c, flow - used));	// 找出增广路上最少的流量 
            if (mi) {	// 找到增广路 
                edge[i].c -= mi;	//正向边- 
                edge[i ^ 1].c += mi;	//反向边+ 
                used += mi;	//当前点流量+ 
            }
            if (used == flow)	//u的能流出的流量流完 
                return used;
        }
    }
    //前半段和Dinic一模一样
    //如果已经到了这里,说明该点出去的所有点都已经流过了
    //并且从前面点传过来的流量还有剩余
    //则此时,要对该点更改dep
    //使得该点与该点出去的点分隔开
    curedge[u] = head[u]; 	//当前狐优化退回到最初	
    --gap[depth[u]];	//深度为depth[u] 
    /*
    这里要解释一下为什么要统计每个深度的点数:
	为了优化!
	?
	统计每个深度对应点数只为了这句话:
	if (gap[depth[u]] == 0)	//出现断层,无法到达t了 
        depth[s] = n + 1;
    因为我们是按照深度来往前走的,路径上的点的深度一定是连续的,而t的深度为0,
	如果某个深度的点不存在,那么我们就无法到达t了
	*/
    if (gap[depth[u]] == 0)	//出现断层,无法到达t了 
        depth[s] = n + 1;
    depth[u]++;	// 层数++ 
    gap[depth[u]]++;	//层数对应个数++ 
    return used;
}
int ISAP() {
    maxflow = 0;
    bfs();
    for (int i = 0; i <= n; ++i) curedge[i] = head[i];
    while (depth[s] < n) {
        dfs(s, inf);
    }
    return maxflow;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值