Flow Problem HDU - 3549 最大流

题解

模板题。。dinic求最大流。

AC代码

#include 
#include 
#define fst first
#define sed second
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
const int N = 20;
const int M = 1e3 + 10;
int n, m;
int dis[N], cur[N]; //cur上次DFS每个节点最后访问的边

struct edge
{
	int v, w, nxt;
}e[M * 2];
int h[N], idx;
void AddEdge(int u, int v, int w)
{
	e[idx] = { v, w, h[u] };
	h[u] = idx++; //后++编号0到idx-1 结束为-1
}
bool BFS(int st, int ed) //每个点相对于st的层次 也就是边权为1的最短路
{
	queue<int> q;
	memset(dis, -1, sizeof(dis));
	dis[st] = 0;
	q.push(st);
	while (!q.empty())
	{
		int u = q.front(); q.pop();
		for (int i = h[u]; ~i; i = e[i].nxt)
		{
			int v = e[i].v, w = e[i].w;
			if (dis[v] == -1 && w) //未访问并且没有满流
				dis[v] = dis[u] + 1, q.push(v);
		}
	}
	return dis[ed] != -1; //返回st是否和ed连通
}
int DFS(int x, int ed, int flow) //从x出发寻找到ed的增广路
{
	if (x == ed)
		return flow; //增广宽度
	int s = 0; //出量总和
	for (int i = cur[x]; ~i; i = e[i].nxt) //从上次最后访问的i开始
	{
		int y = e[i].v, w = e[i].w;
		if (dis[y] == dis[x] + 1 && w) //只向下一层节点进行递归防止舍近求远 且没满流
		{
			int res = DFS(y, ed, min(w, flow - s)); //总流量不超边权 出量不超入量
			cur[x] = i; //记录节点最后的i
			e[i].w -= res, e[i ^ 1].w += res; //编号^1为反向边
			s += res;
			if (s == flow) //出量=入量
				break;
		}
	}
	return s;
}
int Dinic(int st, int ed) //求st到ed的最大流
{
	int res = 0;
	while (BFS(st, ed))
	{
		memcpy(cur, h, sizeof(h)); //初始记录为h
		res += DFS(st, ed, INF); //增广量
	}
	return res;
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int T;
	cin >> T;
	for (int ti = 1; ti <= T; ++ti)
	{
		memset(h, -1, sizeof(h));
		idx = 0;
		scanf("%d%d", &n, &m);
		for (int i = 0; i < m; ++i)
		{
			int u, v, w;
			scanf("%d%d%d", &u, &v, &w);
			AddEdge(u, v, w);
			AddEdge(v, u, 0); //反向边权为0
		}
		printf("Case %d: %d\n", ti, Dinic(1, n));
	}

	return 0;
}

你可能感兴趣的:(___图论___,最大流)