#include <iostream>
#include <algorithm>
#include <vector>

using namespace std;

const int MAXN = 5005;

int N, M;

struct Edge {
int u, v, w;
Edge(int u = 0, int v = 0, int w = 0) : u(u), v(v), w(w) {}
};

bool operator<(const Edge &e1, const Edge &e2) {
return e1.w < e2.w;
}

int p[MAXN];

int find(int x) {
if (x == p[x]) return x;
return p[x] = find(p[x]);
}

int main() {
cin >> N >> M;

Copy code
vector<Edge> edges;

for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= M; j++) {
        int w;
        cin >> w;
        if (j < M) edges.push_back(Edge(i*M + j, i*M + j + 1, w));
        if (i < N) edges.push_back(Edge(i*M + j, (i+1)*M + j, w));
    }
}

sort(edges.begin(), edges.end());

for (int i = 1; i <= N*M; i++) p[i] = i;

int ans = 0;

for (int i = 0; i < edges.size(); i++) {
    int u = edges[i].u, v = edges[i].v, w = edges[i].w;
    int pu = find(u), pv = find(v);
    if (pu != pv) {
        ans++;
        p[pu] = pv;
    }
}

cout << ans << endl;

return 0;
}