#include <bits/stdc++.h>
using namespace std;
const int N = 2000, M = 1e5 + 10, INF = 0x3f3f3f3f;
int n, m, cnt, s, t;
int h[N], nxt[M], e[M], idx = 2, w[M], cur[N];
int mp[60][60];
int gap[N], dep[N];
namespace details {
void add(int a, int b, int c) {
e[idx] = b, w[idx] = c, nxt[idx] = h[a], cur[a] = h[a] = idx++;
}
}
void add(int a, int b, int c) {
details::add(a, b, c), details::add(b, a, 0);
}
void bfs() {
queue<int> q;
q.push(t);
memset(dep, -1, sizeof dep);
gap[dep[t] = 0] = 1;
while (q.size()) {
int u = q.front();
q.pop();
for (int i = h[u]; i; i = nxt[i]) {
int j = e[i];
if (dep[j] == -1) {
gap[dep[j] = dep[u] + 1]++;
q.push(j);
}
}
}
}
int dfs(int u, int flow) {
if (u == t)
return flow;
int used = 0;
for (int i = h[u]; i; i = nxt[i]) {
cur[u] = i;
int j = e[i];
if (dep[j] == dep[u] - 1 && w[i] > 0) {
int f = dfs(j, min(w[i], flow - used));
w[i] -= f, w[i ^ 1] += f;
used += f;
if (used == flow) {
cur[u] = h[u];
return flow;
}
}
}
cur[u] = h[u];
if (!--gap[dep[u]])
dep[s] = n * m * 2 - cnt + 2;
++gap[++dep[u]];
return used;
}
int isap() {
int maxflow = 0;
bfs();
while (dep[s] < n * m * 2 - cnt + 2)
maxflow += dfs(s, 1 << 29);
return maxflow;
}
int point1(int i, int j) {
return (i - 1) * n + j;
}
int point2(int i, int j) {
return point1(i, j) + n * m;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen(".in", "r", stdin);
#else
cin.tie(0)->sync_with_stdio(0);
#endif
cin >> m >> n;
s = N - 5, t = s + 1;
int dx[] = { 1, -1, 0, 0 }, dy[] = { 0, 0, 1, -1 };
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) {
cin >> mp[i][j];
if (mp[i][j] == 0) {
add(s, point1(i, j), INF);
cnt++;
}
else if (mp[i][j] != -1) {
for (int k = 0; k < 4; ++k) {
int x = dx[k] + i, y = dy[k] + j;
if (x >= 1 && x <= m && y >= 1 && y <= n && mp[x][y] >= 0) {
add(point2(i, j), point1(x, y), INF);
}
}
add(point1(i, j), point2(i, j), mp[i][j]);
}
else
cnt += 2;
if (i == 1 || j == 1 || i == m || j == n)
add(point2(i, j), t, INF);
}
}
cout << isap();
return 0;
}