#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iostream>
#include <utility>
#include <set>
#include <cctype>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <climits>
using namespace std;
#define INF 100000000

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

int minimum_steiner_tree(const vector<int>& T, const vector<vector<int> >& g) {
    const int n = g.size();
    const int numT = T.size();
    if (numT <= 1) return 0;

    vector<vector<int> > d = g;
    for (int k = 0; k < n; k++) {
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                d[i][j] = min(d[i][j], d[i][k] + d[k][j]);
            }
        }
    }

    int OPT[(1<<numT)][n];
    for (int S = 0; S < (1<<numT); S++) {
        for (int x = 0; x < n; x++) {
            OPT[S][x] = INF;
        }
    }
    for (int p = 0; p < numT; p++) {
        for (int q = 0; q < n; q++) {
            OPT[1<<p][q] = d[T[p]][q];
        }
    }
    for (int S = 1; S < (1 << numT); S++) {
        if (!S & (S-1)) continue;
        for (int p = 0; p < n; p++) {
            for (int E = 0; E < S; E++) {
                if ((E|S) == S) {
                    OPT[S][p] = min(OPT[S][p], OPT[E][p] + OPT[S-E][p]);
                }
            }
        }
        for (int p = 0; p < n; p++) {
            for (int q = 0; q < n; q++) {
                OPT[S][p] = min(OPT[S][p], OPT[S][q] + d[p][q]);
            }
        }
    }
    int ans = INF;
    for (int S = 0; S < (1<<numT); S++) {
        for (int q = 0; q < n; q++) {
            ans = min(ans, OPT[S][q] + OPT[(1<<numT)-1-S][q]);
        }
    }
    return ans;
}

int main(void) {
    int H, W;
    while (cin >> H >> W) {
        if (H == 0 && W == 0) break;
        vector<int> T;
        vector<vector<int> > g(H*W, vector<int>(H*W));
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                int a;
                cin >> a;
                if (a == 1) T.push_back(i*W+j);
            }
        }
        if (T.size() <= 0) {
            cout << H*W << endl;
            continue;
        }
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                for (int k = 0; k < H; k++) {
                    for (int l = 0; l < W; l++) {
                        g[i*W+j][k*W+l] = INF;
                    }
                }
                g[i*W+j][i*W+j] = 0;
            }
        }
        for (int y = 0; y < H; y++) {
            for (int x = 0; x < W; x++) {
                for (int i = 0; i < 4; i++) {
                    int nx = x+dx[i];
                    int ny = y+dy[i];
                    if (0 <= nx && nx < W && 0 <= ny && ny < H) {
                        g[y*W+x][ny*W+nx] = 1;
                    }
                }
            }
        }
//        for (int i = 0; i < H*W; i++) {
//            for (int j = 0; j < H*W; j++) {
//                if (g[i][j] == INF) cout << "inf\t";
//                else cout << g[i][j] << "\t";
//            }
//            cout << endl;
//        }
        cout << H*W - (minimum_steiner_tree(T, g) + 1) << endl;
    }
    return 0;
}

Measured memory_bytes: 1416