记录编号 605005 评测结果 AAAAAA
题目名称 752.[BJOI2006] 狼抓兔子 最终得分 100
用户昵称 GravatarOTTF 是否通过 通过
代码语言 C++ 运行时间 1.004 s
提交时间 2025-08-13 12:33:30 内存使用 11.28 MiB
显示代码纯文本

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <utility>
#include <vector>

using namespace std;

template <typename PointT, typename EdgeT>
class GraphWithVector {
	private:
	PointT n;
	vector<vector<pair<PointT, EdgeT>>> graph;

	public:

	GraphWithVector (PointT n = 1e5);
	PointT getN () {return n;}
	void add (PointT u, PointT v, EdgeT w = 1);
	void addBoth (PointT u, PointT v, EdgeT w = 1);
	auto& operator [] (const PointT i) {
		return graph[i];
	}
};

template <typename PointT, typename EdgeT>
GraphWithVector<PointT, EdgeT>::GraphWithVector (PointT n) : n (n) {
	graph.resize(n);
}

template <typename PointT, typename EdgeT>
void GraphWithVector<PointT, EdgeT>::add (PointT u, PointT v, EdgeT w) {
	graph[u].emplace_back(v, w);
}

template <typename PointT, typename EdgeT>
void GraphWithVector<PointT, EdgeT>::addBoth (PointT u, PointT v, EdgeT w) {
	add (u, v, w);
	add (v, u, w);
}

template <typename PointT, typename EdgeT>
class NetworkFlow {
	private:
	PointT n;
	GraphWithVector<PointT, pair<EdgeT, PointT>> nf;

	public:

	NetworkFlow (PointT n = 1e5) : n (n), nf (n) {}
	PointT getN () {return n;}
	void add (PointT u, PointT v, EdgeT w = 1);
	auto& operator [] (const PointT i) {
		return nf[i];
	}
};

template <typename PointT, typename EdgeT>
void NetworkFlow<PointT, EdgeT>::add (PointT u, PointT v, EdgeT w) {
	nf.add(u, v, make_pair (w, nf[v].size()));
	nf.add(v, u, make_pair (w, nf[u].size() - 1));
}

template <typename PointT, typename EdgeT, typename GraphT>
class Dinic {
	private:

	GraphT& graph;
	PointT B;
	PointT E;
	vector<int> dep;
	vector<int> cur;
	EdgeT res;

	bool bfs ();
	EdgeT dfs (PointT now, EdgeT limit);

	public:

	Dinic (GraphT &graphin) : graph (graphin) {
		dep.resize(graph.getN() + 2);
		cur.resize(graph.getN() + 2);
	}
	EdgeT dinic (PointT b, PointT e);
};

template <typename PointT, typename EdgeT, typename GraphT>
bool Dinic<PointT, EdgeT, GraphT>::bfs () {
	fill (dep.begin(), dep.end(), -1);
	fill (cur.begin(), cur.end(), 0);
	
	queue<PointT> q;
	q.push(B);
	dep[B] = 0;
	
	while (!q.empty()) {
		PointT u = q.front();
		q.pop();
		
		for (auto [v, ww] : graph[u]) {
			auto [w, another] = ww;
			if (dep[v] == -1 && w != 0) {
				dep[v] = dep[u] + 1;
				q.push(v);
			}
		}
	}
	
	return (dep[E] != -1);
}

template <typename PointT, typename EdgeT, typename GraphT>
EdgeT Dinic<PointT, EdgeT, GraphT>::dfs (PointT now, EdgeT limit) {
	if (now == E) {
		return limit;
	}
	
	for (int i = cur[now]; i < graph[now].size(); i++) {
		cur[now] = i;

		PointT u = now;
		auto [v, ww] = graph[u][i];
		auto [w, another] = ww;
		
		if (dep[u] + 1 == dep[v] && graph[u][i].second.first != 0) {
			EdgeT t = dfs (v, min (w, limit));
			
			if (t) {
				graph[u][i].second.first -= t;
				graph[v][another].second.first += t;
				return t;
			}
			else {
				dep[v] = -1;
			}
		}
	}
	
	return 0;
}

template <typename PointT, typename EdgeT, typename GraphT>
EdgeT Dinic<PointT, EdgeT, GraphT>::dinic (PointT b, PointT e) {

	res = 0;
	B = b;
	E = e;

	EdgeT flow = 0;
	while (bfs ()) {
		while (flow = dfs (B, 1e9)) {
			res += flow;
		}
	}
	
	return res;
}

int n;
int m;

inline int cal (int x, int y) {
	return (x - 1) * m + y;
}

int main () {
	
	cin >> n >> m;
	NetworkFlow<int, int> nf(n * m + 2);
	int w;
	for (int i = 1; i <= n; i++) {
		for (int j = 1; j < m; j++) {
			cin >> w;
			nf.add(cal (i, j), cal (i, j + 1), w);
		}
	}
	for (int i = 1; i < n; i++) {
		for (int j = 1; j <= m; j++) {
			cin >> w;
			nf.add(cal (i, j), cal (i + 1, j), w);
		}
	}
	for (int i = 1; i < n; i++) {
		for (int j = 1; j < m; j++) {
			cin >> w;
			nf.add(cal (i, j), cal (i + 1, j + 1), w);
		}
	}

	Dinic<int, int, NetworkFlow<int, int>> dinic(nf);

	cout << dinic.dinic(cal(1, 1), cal (n, m)) << endl;
	
	return 0;
}