网络流-最大流 Dinic 配题(HDU 3549)

网络流-求解最大流的算法:

Dinic算法

  • 通过BFS构建层次网络
  • 通过DFS寻找增广路

EK算法

  • 通过BFS找到一条到达汇点的路径,记录该路径
  • 将该路径的残存流量减去路径上的最小流量

配题:HDU 3549

题意:构建网络,寻找点 1 到 点 N 的最大流。

注意:建图时候偶数边都是正向边,奇数边都是反向边,反之亦然。使用前向星建图,可以很好地提取一条正向边的反向边但是使用vector构建的邻接表,要注意构建的手法,graph 和 edge 的构建技术。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;
const int maxN = 20;
const int maxM = 2005;
const int INF = 0x7fffffff; 
struct EDGE
{
	int u, v;
	int flow;
	EDGE(){}
	EDGE(int u, int v, int flow): u(u), v(v), flow(flow){}
};
int N, M;
vector<EDGE>edge;
vector<int>graph[maxN];
int depth[maxN];
int MIN(const int a, const int b)
{
	if (a < b) return a;
	return b;
} 
void add_edge(int u, int v, int cap)
{
	edge.push_back(EDGE(u, v, cap));
	edge.push_back(EDGE(v, u, 0));
	int cnt = edge.size();
	graph[u].push_back(cnt - 2);
	graph[v].push_back(cnt - 1);
}
bool dinic_bfs(int source, int sink)
{
	queue<int>q;
	
	while (!q.empty()) q.pop();
	memset(depth, 0, sizeof(depth));
	
	depth[source] = 1;
	q.push(source);
	
	while (!q.empty())
	{
		int cur_node = q.front();
		q.pop();
		
		for (int i = 0; i < graph[cur_node].size(); i++)
		{
			int id = graph[cur_node][i];
			int next_node = edge[id].v;
			int flow = edge[id].flow;
			if (depth[next_node] == 0 && flow > 0)
			{
				depth[next_node] = depth[cur_node] + 1;
				q.push(next_node);
			}
		}
	}
	
	if (depth[sink])
	{
		return true;
	}
	else
	{
		return false;
	}
}
int dinic_dfs(int cur_node, int sink, int min_flow)
{
	if (cur_node == sink) 
	{
		return min_flow;
	}
	
	for (int i = 0; i < graph[cur_node].size(); i++)
	{
		int id = graph[cur_node][i];
		int next_node = edge[id].v;
		int flow = edge[id].flow;
		if (depth[next_node] == depth[cur_node] + 1 && flow > 0)
		{
			int cut_flow = dinic_dfs(next_node, sink, MIN(min_flow, flow));
			if (cut_flow > 0)
			{
				edge[id].flow -= cut_flow;
				edge[id^1].flow += cut_flow;
				return cut_flow;
			}
		}
	}
	return 0;
}
int Dinic(int source, int sink)
{
	int res = 0;
	while (dinic_bfs(source, sink))
	{
		res += dinic_dfs(source, sink, INF);
	}
	return res;
}
int main()
{
	int T;
	int Case = 1;
	cin>> T;
	while (T--)
	{
		cin>> N>> M;
		edge.clear();
		for (int i = 1; i <= N; i++)
		{
			graph[i].clear();
		}
		for (int i = 1; i <= M; i++)
		{
			int a, b, c;
			cin>> a>> b>> c;
			add_edge(a, b, c);
			add_edge(b, a, 0);
		}
		int res = Dinic(1, N);
		cout<< "Case "<< Case++<< ": "<< res<< endl;
	}
	return 0;
}
发布了331 篇原创文章 · 获赞 135 · 访问量 11万+

猜你喜欢

转载自blog.csdn.net/Triple_WDF/article/details/102406725