/**
    F11 COMPETITION
    Problema: insule
    Runda: 3
    Echipa: Quicksilver
**/

#include <algorithm>
#include <fstream>
#include <vector>

#include <iostream>

using namespace std;

#define INPUT "insule.in"
#define OUTPUT "insule.out"
#define MAX_DIM 501

const int dx[] = { 0, -1,  0,  1};
const int dy[] = { 1,  0, -1,  0};

int nRows, nCols, nIslands, totalCost;
int father[MAX_DIM * MAX_DIM], rank[MAX_DIM * MAX_DIM];
int map[MAX_DIM][MAX_DIM];
vector<pair<pair<int, int>, int> > bridges, newBridges;

/** DEBUG **/
void printMap() {
    for (int i = 1; i <= nRows; ++i) {
        for (int j = 1; j <= nCols; ++j)
            cout << map[i][j] << " ";
        cout << "\n";
    }
    cout << "\n";
}

void printBridges(vector<pair<pair<int, int>, int> > bridges) {
    for (int i = 0; i < int(bridges.size()); ++i) {
        cout << bridges[i].first.first << " ";
        cout << bridges[i].first.second << " ";
        cout << bridges[i].second << "\n";
    }
    cout << "\n";
}

/** READ **/
void read() {
    ifstream fin(INPUT);
    fin >> nRows;
    fin >> nCols;
    fin.ignore(1, '\n');
    char buff[MAX_DIM];
    for (int i = 1; i <= nRows; ++i) {
        fin.getline(buff, MAX_DIM);
        for (int j = 1; j <= nCols; ++j)
            map[i][j] = (buff[j - 1] - '0') * (-1);
    }
    fin.close();
}

/** SOLVE **/
struct cmp {
    bool operator()(pair<pair<int, int>, int> firstBridge, pair<pair<int, int>, int> secondBridge) {
        return (firstBridge.first.first < secondBridge.first.first) ||
            (firstBridge.first.first == secondBridge.first.first && firstBridge.first.second < secondBridge.first.second) ||
            (firstBridge.first.first == secondBridge.first.first && firstBridge.first.second == secondBridge.first.second && firstBridge.second < secondBridge.second);
    }
};

struct newCmp {
    bool operator()(pair<pair<int, int>, int> firstBridge, pair<pair<int, int>, int> secondBridge) {
        return firstBridge.second < secondBridge.second;
    }
};

void fillMap(int x, int y) {
    map[x][y] = nIslands;
    for (int i = 0; i < 4; ++i)
        if (map[x + dx[i]][y + dy[i]] == -1)
            fillMap(x + dx[i], y + dy[i]);
}

int find(int node) {
    if (node != father[node])
        father[node] = find(father[node]);
    return father[node];
}

void unite(int firstFather, int secondFather) {
    if (rank[firstFather] < rank[secondFather])
        father[firstFather] = secondFather;
    else
        father[secondFather] = firstFather;
    if (rank[firstFather] == rank[secondFather])
        ++rank[firstFather];
}

void solve() {
    for (int i = 1; i <= nRows; ++i)
        for (int j = 1; j <= nCols; ++j)
            if (map[i][j] == -1) {
                ++nIslands;
                fillMap(i, j);
            }

    // printMap();

    int prevIslandInd, firstIsland, secondIsland, cost;
    for (int i = 1; i <= nRows; ++i) {
        prevIslandInd = 0;
        for (int j = 1; j <= nCols; ++j)
            if (map[i][j] > 0) {
                if (prevIslandInd > 0 && map[i][prevIslandInd] != map[i][j]) {
                    firstIsland = min(map[i][prevIslandInd], map[i][j]);
                    secondIsland = max(map[i][prevIslandInd], map[i][j]);
                    cost = j - prevIslandInd - 1;
                    bridges.push_back(make_pair(make_pair(firstIsland, secondIsland), cost));
                }
                prevIslandInd = j;
            }
    }

    // printBridges(bridges);

    for (int j = 1; j <= nCols; ++j) {
        prevIslandInd = 0;
        for (int i = 1; i <= nRows; ++i)
            if (map[i][j] > 0) {
                if (prevIslandInd > 0 && map[prevIslandInd][j] != map[i][j]) {
                    firstIsland = min(map[prevIslandInd][j], map[i][j]);
                    secondIsland = max(map[prevIslandInd][j], map[i][j]);
                    cost = i - prevIslandInd - 1;
                    bridges.push_back(make_pair(make_pair(firstIsland, secondIsland), cost));
                }
                prevIslandInd = i;
            }
    }

    // printBridges(bridges);

    sort(bridges.begin(), bridges.end(), cmp());
    for (int i = 0; i < int(bridges.size()); ++i) {
        firstIsland = bridges[i].first.first;
        secondIsland = bridges[i].first.second;
        cost = bridges[i].second;
        newBridges.push_back(make_pair(make_pair(firstIsland, secondIsland), cost));
        while(i < int(bridges.size()) - 1 && bridges[i].first.first == bridges[i + 1].first.first && bridges[i].first.second == bridges[i + 1].first.second)
            ++i;
    }

    // printBridges(newBridges);

    sort(newBridges.begin(), newBridges.end(), newCmp());

    // printBridges(newBridges);

    for (int i = 1; i <= nIslands; ++i)
        father[i] = i;
    int firstFather, secondFather;
    for (int i = 0; i < int(newBridges.size()); ++i) {
        firstFather = find(newBridges[i].first.first);
        secondFather = find(newBridges[i].first.second);
        if (firstFather != secondFather) {
            unite(firstFather, secondFather);
            totalCost += newBridges[i].second;
        }
    }
}

/** PRINT **/
void print() {
    ofstream fout(OUTPUT);
    fout << totalCost;
    fout.close();
}

/** MAIN **/
int main() {
    read();
    solve();
    print();
    return 0;
}
