版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38081836/article/details/83513027
现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,
而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:
左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路
1:(x,y)<>(x+1,y)
2:(x,y)<>(x,y+1)
3:(x,y)<==>(x+1,y+1)
道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,
开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击
这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,
才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的
狼的数量要最小。因为狼还要去找喜羊羊麻烦.
Input
第一行为N,M.表示网格的大小,N,M均小于等于1000.
接下来分三部分
第一部分共N行,每行M-1个数,表示横向道路的权值.
第二部分共N-1行,每行M个数,表示纵向道路的权值.
第三部分共N-1行,每行M-1个数,表示斜向道路的权值.
输入文件保证不超过10M
Output
输出一个整数,表示参与伏击的狼的最小数量.
Sample Input
3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6
Sample Output
14
分析:我们肯定要堵住所有的通往终点的路口才行,也就是让起电与终点不连通,也就是求最小割,也就是求最大流。dinic水过。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define g getchar()
#define rep(i, a, b) for(int i = a; i <= b; i++)
#define per(i, a, b) for(int i = a; i >= b; i--)
#define met(a, b) memset(a, b, sizeof(a))
const int maxn = 1e6 + 10;
const int inf = 0x3f3f3f3f;
inline int read() {
int res = 0, f = 1;
char ch = g;
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = g;}
while(ch >= '0' && ch <= '9') {res = res * 10 + ch - '0'; ch = g;}
return res * f;
}
int head[maxn * 6], u[maxn * 6], v[maxn * 6], w[maxn * 6], top = 0, S, T, cur[maxn], dep[maxn], Next[maxn * 6];
void init() {
met(head, -1);
top = 0;
}
void addEdge(int U, int V, int W) {
//printf("%d -> %d %d\n", U, V, W);
u[top] = U;
v[top] = V;
w[top] = W;
Next[top] = head[U];
head[U] = top++;
u[top] = V;
v[top] = U;
w[top] = W;
Next[top] = head[V];
head[V] = top++;
}
bool BFS() {
//cout << "BFS" << endl;
met(dep, 0);
queue<int> q;
while(!q.empty()) q.pop();
q.push(S);
dep[S] = 1;
while(!q.empty()) {
int now = q.front();
q.pop();
for(int i = head[now]; i != -1; i = Next[i]) {
int vv = v[i];
if(dep[vv] == 0 && w[i] > 0) {
dep[vv] = dep[now] + 1;
q.push(vv);
}
}
}
if(dep[T] == 0) return 0;
else return 1;
}
int DFS(int u, int flow) {
if(u == T) return flow;
for(int &i = cur[u]; i != -1; i = Next[i]) {
if(dep[v[i]] == dep[u] + 1 && w[i] > 0) {
//cout << flow << " "<< w[i] << endl;
int di = DFS(v[i], min(flow, w[i]));
if(di > 0) {
//cout << "DFS" << endl;
w[i] -= di;
//cout << w[i] << endl;
w[i ^ 1] += di;
return di;
}
}
}
return 0;
}
int dinic() {
int ans = 0;
while(BFS()) {
for(int i = S; i <= T; i++) {
cur[i] = head[i];
}
while(int d = DFS(S, inf)) {
ans += d;
}
//cout << ans << endl;
}
return ans;
}
void input() {
init();
int n = read(), m = read(), cal;
S = 1, T = n * m;
int tot = 2;
rep(i, 1, n) {
rep(j, 2, m) {
cal = read();
addEdge(tot - 1, tot, cal);
tot++;
}
tot++;
}
tot = m + 1;
rep(i, 1, n - 1) {
rep(j, 1, m) {
cal = read();
addEdge(tot - m, tot, cal);
tot++;
}
//tot++;
}
tot = m + 2;
rep(i, 1, n - 1) {
rep(j, 1, m - 1) {
cal = read();
addEdge(tot - m - 1, tot, cal);
//cout << tot - m - 1 << " " << tot <<endl;
tot++;
}
tot++;
}
printf("%d\n", dinic());
}
int main() {
input();
return 0;
}