【Dinic算法最大流】网络最大流 洛谷P3376

题目描述

如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入输出格式

输入格式:

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数ui、vi、wi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi)

输出格式:

一行,包含一个正整数,即为该网络的最大流。

输入输出样例

输入样例#1: 复制

4 5 4 3
4 2 30
4 3 20
2 3 20
2 1 30
1 3 40

输出样例#1: 复制

50

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=25

对于70%的数据:N<=200,M<=1000

对于100%的数据:N<=10000,M<=100000

样例说明:

题目中存在3条路径:

4-->2-->3,该路线可通过20的流量

4-->3,可通过20的流量

4-->2-->1-->3,可通过10的流量(边4-->2之前已经耗费了20的流量)

故流量总计20+20+10=50。输出50。

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

const int inf = 0x7fffffff;
const int mn = 1e4 + 10, mm = 1e5 + 10;

int edge;
int fr[mn];
int cur[2 * mn]; /// 当前弧优化
int lv[4 * mn];
struct node
{
	int to, val, nx, fan;
} e[2 * mm];

void addedge(int u, int v, int w)
{
	edge++;
	e[edge].to = v, e[edge].val = w, e[edge].nx = fr[u], e[edge].fan = edge + 1;
	fr[u] = edge;
	edge++;
	e[edge].to = u, e[edge].val = 0, e[edge].nx = fr[v], e[edge].fan = edge - 1;
	fr[v] = edge;
}

void bfs(int s)
{
	memset(lv, 0, sizeof lv);
	lv[s] = 1;
	queue<int> q;
	q.push(s);
	while (!q.empty())
	{
		int t = q.front();
		q.pop();
		for (int i = fr[t]; i != -1; i = e[i].nx)
		{
			if (e[i].val > 0 && !lv[e[i].to])
			{
				lv[e[i].to] = lv[t] + 1;
				q.push(e[i].to);
			}
		}
	}
}

int dfs(int s, int t, int f)
{
	if (s == t)
		return f;
	for (int &i = cur[s]; i != -1; i = e[i].nx)
	{
		if (e[i].val > 0 && lv[s] < lv[e[i].to])
		{
			int d = dfs(e[i].to, t, min(f, e[i].val));
			if (d > 0)
			{
				e[i].val -= d;
				e[e[i].fan].val += d;
				return d;
			}
		}
	}
	return 0;
}

int main()
{
	freopen("D:\\in.txt", "r", stdin);
	memset(fr, -1, sizeof fr);
	int n, m, s, t;
	scanf("%d %d %d %d", &n, &m, &s, &t);
	while (m--)
	{
		int u, v, w;
		scanf("%d %d %d", &u, &v, &w);
		addedge(u, v, w);
	}

	int flow = 0;
	while (1)
	{
		bfs(s);
		if (!lv[t])
			break;
		for (int i = 1; i <= n; i++)
			cur[i] = fr[i];

		int f = 0;
		while ((f = dfs(s, t, inf)) > 0)
			flow += f;
	}
	printf("%d\n", flow);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/ummmmm/article/details/81280454