#include<iostream>
#include<climits>
#include<cassert>
using namespace std;
#define rep(i, n) for ( int i = 0; i < n; i++ )
#define MAX 12
#define HMAX 10

enum {EAST, NORTH, WEST, SOUTH};
enum {START, DIG};

int H, W;
bool in[MAX][MAX];
bool aV[MAX][MAX];

int V[MAX][MAX];

int adj[MAX][MAX][4];

pair<int, int> P[MAX][MAX], ans[MAX][MAX];

int minc;
int limit;

int getMD(){
 int md = 0;
 rep(i, H) rep(j, W){
   if ( in[i][j] && V[i][j] == 0 ) md++;
 }
 return md;
}

void dfs( int mode, int cost, int pi, int pj, int id ){

   if ( mode == START ){
       bool start = false;
       rep( i, H ) rep( j, W ){
           if ( in[i][j] && V[i][j] == 0 && !start){
               start = true;
               V[i][j] = id;
               dfs( DIG, cost+1, i, j, id);
               V[i][j] = 0;
           }
       }
       if ( !start ){ // solved
           if ( cost < minc ){
               rep(i, H) rep(j, W) ans[i][j] = P[i][j];
               rep(i, H) rep(j, W) aV[i][j] = V[i][j];
               minc = cost;
           }
       }
       return;
   } else { // DIG
       if ( cost > minc ) return;

       int ni, nj;

       for ( int r = 0; r < 4; r++ ){
           if ( r % 2 == 0 ){
               ni = pi;
               nj = adj[pi][pj][r];
           } else {
               ni = adj[pi][pj][r];
               nj = pj;
           }
           if ( ni < 0 || nj < 0) continue;

           if ( V[ni][nj] == 0){ // continue dig
               V[ni][nj] = id;
               int d = max(pi, ni)-min(pi, ni) + max(pj, nj)-min(pj, nj);
               dfs( DIG, cost + d, ni, nj, id );
               V[ni][nj] = 0;
           } else if ( V[ni][nj] < id ){ // to start
               int d = max(pi, ni)-min(pi, ni) + max(pj, nj)-min(pj, nj);
               dfs( START, cost+d-1, -1, -1, id+1 );

           }
       }
   }
}

int si, sj;

void compute(){
   rep(i, H) rep(j, W) V[i][j] = 0;
   V[si][sj] = 1;

   minc = 100;

   dfs( START, 1, -1, -1, 2 );

       cout << H*W-minc << endl;
}

void makePath(){
   bool row[MAX][MAX], col[MAX][MAX];
   int C[MAX][MAX];
   rep(i, H) rep(j, W) row[i][j] = col[i][j] = false;
   rep(i, H) rep(j, W){
       if ( in[i][j] ){
           rep(a, H) col[a][j] = true;
           rep(b, W) row[i][b] = true;
       }
   }
   rep(i, H) rep(j, W) C[i][j] = (row[i][j]&&col[i][j] ? 1 : 0);

   int pre;
   rep(i, H) {
     for ( int j = 0, pre = -1; j < W; j++ ){
       if ( C[i][j] ){ adj[i][j][WEST] = pre; pre = j; }
     }
     for ( int j = W-1, pre = -1; j >= 0; j-- ){
       if ( C[i][j] ){ adj[i][j][EAST] = pre; pre = j; }
     }
   }
   rep(j, W){
       for ( int i = 0, pre = -1; i < H; i++ ){
           if ( C[i][j] ){ adj[i][j][NORTH] = pre; pre = i;}
       }
       for ( int i = H-1, pre = -1; i  >= 0; i-- ){
           if ( C[i][j] ){ adj[i][j][SOUTH] = pre; pre = i; }
       }
   }
}

int getDist( pair<int, int> p1, pair<int, int > p2 ){
   return max(p1.first, p2.first)-min(p1.first, p2.first) +
       max(p1.second, p2.second)-min(p1.second, p2.second);
}
void setLimit(){
   pair<int, int > nodes[HMAX];
   int nnode = 0;
   rep(i, H) rep(j, W) if ( in[i][j] ) nodes[nnode++] = make_pair(i, j);
   bool used[HMAX] = {};
   int d[HMAX];

   rep(i, nnode) d[i] = INT_MAX;

   d[0] = 0;

   limit = 1;
   while(1){
       int minv = INT_MAX;
       int u;
       rep(i, nnode){
           if ( !used[i] && d[i] < minv ){
               minv = d[i];
               u = i;
           }
       }
       if ( minv == INT_MAX ) break;
       limit += d[u];
       used[u] = true;

       int md;
       rep(v, nnode ){
           if ( used[v] ) continue;
           md = getDist(nodes[u], nodes[v]);
           d[v] = min( d[v], md );
       }
   }
}

int main(){
   while ( cin >> H >> W && H ){
       si = sj = -1;
       int h = 0;
       rep(i, H) rep(j, W) {
           cin >> in[i][j];
           if ( in[i][j] ) h++;
           if ( si == - 1 && in[i][j]){
               si = i; sj = j;
           }
       }
       makePath();
       setLimit();
       compute();
   }
   return 0;
}

Measured memory_bytes: 0