Flow Problem HDU - 3549 最大流

題解

模板題。。dinic求最大流。

AC代碼

#include <stdio.h>
#include <bits/stdc++.h>
#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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章