#include <bits/stdc++.h>

using namespace std;

inline int toInt(string s) {int v; istringstream sin(s);sin>>v;return v;}
template<class T> inline string toString(T x) {ostringstream sout;sout<<x;return sout.str();}
template<class T> inline T sqr(T x) {return x*x;}

typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<string> vs;
typedef pair<int, int> pii;
typedef long long ll;

#define all(a)  (a).begin(),(a).end()
#define rall(a) (a).rbegin(), (a).rend()
#define pb push_back
#define mp make_pair
#define each(i,c) for(typeof((c).begin()) i=(c).begin(); i!=(c).end(); ++i)
#define exist(s,e) ((s).find(e)!=(s).end())
#define range(i,a,b) for(int i=(a);i<(b);++i)
#define rep(i,n)  range(i,0,n)
#define clr(a,b) memset((a), (b) ,sizeof(a))
#define dump(x)  cerr << #x << " = " << (x) << endl;
#define debug(x) cerr << #x << " = " << (x) << " (L" << __LINE__ << ")" << " " << __FILE__ << endl;

const double eps = 1e-10;
const double pi  = acos(-1.0);
const ll INF =1LL << 62;
const int inf =1 << 29;

const int tmax=11;
const int vmax=150;

int V,T;
int d[vmax][vmax];
int t[tmax];
int p[1<<tmax][vmax];


int minimum_steiner_tree(){
	if(T<=1)
		return 0;

	rep(k,vmax)rep(i,vmax)rep(j,vmax) d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
	rep(i,1<<tmax)rep(j,vmax) p[i][j]=inf;

	rep(i,T){
		rep(j,V) p[1<<i][j]=d[t[i]][j];
		rep(j,T) p[1<<i|1<<j][t[j]]=d[t[i]][t[j]];
	}

	for(int k=2;k<T;++k){
		for(int s=(1<<k)-1;(s<(1<<T));){
			rep(x,V){
				int ns=s;
				int cur=-1;
				rep(i,T) if(t[i]==x) cur=i;
				if(cur!=-1) ns|=(1<<cur);
				if(cur!=-1&&s==ns) continue;
				for(int u=(s-1)&s;u!=0;u=(u-1)&s){
					int c=(s&(~u));
					p[ns][x]=min(p[ns][x],p[u][x]+p[c][x]);
				}
			}
			int x=s&-s,y=s+x;
			s=((s&~y)/x>>1)|y;
		}
		for(int s=(1<<k)-1;(s<(1<<T));){
			rep(x,V){
				int ns=s;
				int next=-1;
				rep(i,T) if(t[i]==x) next=i;
				if(next!=-1) ns|=(1<<next);
				if(next!=-1&&s==ns) continue;
				rep(y,V) p[ns][x]=min(p[ns][x],p[s][y]+d[y][x]);
			}
			int x=s&-s,y=s+x;
			s=((s&~y)/x>>1)|y;
		}
	}

	const int mask=(1<<T)-1;
	int ans=p[mask][0];
	rep(i,vmax) ans=min(ans,p[mask][i]);
	return ans;
}

int main(void){
	int h,w;
	while(cin >> h >> w){
		if(h==0)
			break;
		rep(i,vmax)rep(j,vmax) d[i][j]=(i==j)?0:inf;
		V=h*w,T=0;

		rep(i,h*w){
			int in;
			cin >> in;
			if(in) t[T++]=i;
		}
		rep(i,h)rep(j,w){
			int cur=w*i+j;
			if(i+1<h) d[cur][cur+w]=d[cur+w][cur]=1;
			if(j+1<w) d[cur][cur+1]=d[cur+1][cur]=1;
		}
		int res=minimum_steiner_tree();
		cout << V-1-res << endl;
	}
	return 0;
}



// q[s|c][x]=min(q[s|c],p[s][x]+p[c][x]);

// p[s][x]=min(p[s][x],p[s][y]+d[y][x]) y&#8714;s
// p[s][x]=min(p[s][x],q[s][y]+d[y][x]) y&#8714;v/s