网络流的部分优化

本文主要记录了网络流中的ISAP优化方法,这是一种在最大流算法基础上的改进。内容包括当前弧优化,即在每次增广路径后删除已使用的边,以及进阶的分层图优化,虽然分层图优化的细节如gap优化和dep[u]的递增不甚理解,但仍然是算法优化的重要部分。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

只是帮助自己记忆一下。

ISAP应该是一种复杂度比较优秀的最大流算法。
具体优化分为两部分,都是基于dinic之上的。
1.1.1.当前弧优化,这种优化比较显然,就是对于每一次流,每条边一定是只经过一次的,那么这样就可以将每条流过的变在链式前向星中删掉。
2.2.2.进阶版分层图优化。这个现在不是很理解。不过只留dep[u]==dep[v]+1dep[u] == dep[v] + 1dep[u]==dep[v]+1这部分比较显然,不过用gapgapgap优化的每次将dep[u]++dep[u] ++dep[u]++并不是很理解,暂时留个坑,只能感性理解。

#include <cstdio>
#include <queue>
using namespace std;

const int N = 1e4 + 10;
const int M = 1e5 + 10;
const int inf = 1e9 + 7;
struct Edge{
	int to,next,val;
} f[M << 1];
int n,m,s,t,gap[N],dep[N],head[N],stu[N],ans,cnt;
queue <int> q;

int read()
{
	int x = 0,w = 1;
	char ch = getchar();
	while (ch < '0' || ch > '9') {if (ch == '-') w = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
	return x * w;
}

int min(int a,int b) {return a < b ? a : b;}

void add(int u,int v,int w)
{
	f[++ cnt].to = v;
	f[cnt].val = w;
	f[cnt].next = stu[u];
	stu[u] = cnt;
}

void init()
{
	for (int i = 1; i <= n; i ++) head[i] = stu[i];
	q.push(t);
	gap[dep[t] = 1] = 1;
	while (!q.empty())
	{
		int u = q.front();
		q.pop();
		for (int i = head[u]; i; i = f[i].next)
			if (!dep[f[i].to])
				++ gap[dep[f[i].to] = dep[u] + 1],q.push(f[i].to);
	}
}

int flo(int u,int mi)
{
	if (u == t) return mi;
	int flow = 0;
	for (int &i = head[u]; i; i = f[i].next)
		if (dep[u] == dep[f[i].to] + 1)
		{
			int res = flo(f[i].to,min(mi,f[i].val));
			flow += res;
			mi -= res;
			f[i].val -= res;
			f[i ^ 1].val += res;
			if (!mi) return flow;
		}
	if (!(-- gap[dep[u]])) dep[s] = n + 1;
	++ gap[++ dep[u]],head[u] = stu[u];
	return flow;
}

int ISAP()
{
	init();
	int res = flo(s,inf);
	while (dep[s] <= n) res += flo(s,inf);
	return res;
}

int main()
{
	cnt = 1;
	n = read(),m = read(),s = read(),t = read();
	for (int i = 1,u,v,w; i <= m; i ++)	
		u = read(),v = read(),w = read(),add(u,v,w),add(v,u,0);
	printf("%d\n",ISAP());
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值