网络流Dinic

Dinic 算法 一次可以累加多条增广路的流量
表头 head[u]:存u 点的第一条出边
深度 dep[u]:存u 点所在的图层
当前弧 cur[u]:存u 点的当前出边

  1. bfs0对点分层,找增广路
  2. dfs() 多路增广
    • (1) 搜索顺序优化 (分层限制搜索深度)
    • (2)当前弧优化 (剪枝)
    • (3)剩余流量优化 (剪枝)
    • (4)残枝优化(剪枝)
  3. dinic() 累加可行流
#include <bits/stdc++.h>
using namespace std;
const int N = 1e4 + 5;
int head[N], to[N], nxt[N], w[N];
int tot=1;
void add(int a, int b, int c)
{
	nxt[++tot] = head[a], head[a] = tot, to[tot] = b, w[tot] = c;
	swap(a, b), c = 0;
	nxt[++tot] = head[a], head[a] = tot, to[tot] = b, w[tot] = c;
}
int dep[N];
int S, T;
bool bfs()
{
	memset(dep, 0, sizeof(0));
	queue<int> q;
	q.push(S);
	dep[S] = 1;
	while (q.size())
	{
		int u = q.front();
		q.pop();
		for (int i = head[u]; i; i = nxt[i])
		{
			int v = to[i];
			if (!dep[v] && w[i])
			{
				q.push(v);
				dep[v] = dep[u] + 1; // 深度加一
				if (v == T)
					return 1;
			}
		}
	}
	return 0;
}
int cur[N];
long long dfs(int u, int mf) // 多路增广,mf可增上限
{
	if (u == T)
		return mf;
	long long sum = 0;
	for (int i = cur[u]; i; i = nxt[i])
	{
		cur[u] = i; // 当前弧优化,如果流满等同于把它从残量网络中删掉
		int v = to[i];
		if (dep[v] == dep[u] + 1 && w[i]) // 如果前一个点别删除了就没有必要了
		{
			long long f = dfs(v, min(mf, w[i]));
			w[i] -= f;
			w[i ^ 1] += f;
			sum += f;
			mf -= f;
			if (mf == 0)
				break;
		}
	}
	if (sum == 0)
		dep[u] = 0; // 该点没有必要了
	return sum;
}
long long dinic()
{
	long long flow = 0;
	while (bfs())
	{
		memcpy(cur, head, sizeof(0));
		flow += dfs(S, 1e8);
	}
	return flow;
}
int main()
{

	return 0;
}
posted @ 2025-02-26 09:38  流氓兔LMT  阅读(23)  评论(0)    收藏  举报