#include<stdio.h>
#include<algorithm>
#include<vector>
using namespace std;
int c[15][15];
int g[200][200];
typedef int weight;
int n;
int d[200][200];
int ABS(int a){return max(a,-a);}
weight minimum_steiner_tree(const vector<int>& T) {
  const int numT = T.size();
  if (numT <= 1) return 0;
for(int i=0;i<n;i++)for(int j=0;j<n;j++)d[i][j]=99999999;

for(int i=0;i<n;i++)for(int j=0;j<n;j++)if(g[i][j])d[i][j]=1;
for(int i=0;i<n;i++)d[i][i]=0;
  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] );

  weight OPT[(1 << numT)][n];
  for (int S = 0; S < (1 << numT); ++S)
    for (int x = 0; x < n; ++x)
      OPT[S][x] = 99999999;

  for (int p = 0; p < numT; ++p) // trivial case
    for (int q = 0; q < n; ++q)
      OPT[1 << p][q] = d[T[p]][q];

  for (int S = 1; S < (1 << numT); ++S) { // DP step
    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] );
  }
  weight ans = 99999999;
  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(){
	int a,b;
	while(scanf("%d%d",&a,&b),a){
		for(int i=0;i<a;i++)for(int j=0;j<b;j++)scanf("%d",&c[i][j]);
		for(int i=0;i<200;i++)for(int j=0;j<200;j++)g[i][j]=0;
		vector<int>t;
		for(int i=0;i<a*b;i++){
			if(c[i/b][i%b])t.push_back(i);
			for(int j=0;j<a*b;j++){
				if(ABS(i/b-j/b)+ABS(i%b-j%b)==1)g[i][j]=1;
			}
		}
		n=a*b;
		int ret=minimum_steiner_tree(t);
		printf("%d\n",a*b-ret-1);
	}
}