Problem:
Problem F:
Chocolate with Heart Marks
太郎君はチョコレートが大好きで, 学校から帰るとハートマークが描かれたお気に入りの板チョコを食べます, 最近の楽しみは, すべてのハートマークのブロックを最後まで残すように食べることです. 太郎君は, すべてのハートマークのブロックがつながったまま, できるだけ多くのハートマークのないブロックを食べようとします.
しかし太郎君はまだ幼く, 上記のように食べようとしても無駄なブロックが残ってしまいます. そこで太郎君は, すべてのハートマークのブロックをつながったまま残すときに食べられる最大のブロック数を求めるプログラムの作成をあなたに依頼しました.
太郎君は, すべてのハートマークのブロックがつながっている限り、どんな食べ方をしてもかまいません. ブロックのいずれか一辺が他のブロックに接していないと分かれていることになります.
Input
入力は複数のデータセットからなります. 各データセットは以下の形式で与えられます:
H W
H
×
W
個の数字
H
,
W
はそれぞれ板チョコの縦のサイズ, 横のサイズを示す整数です.
H
×
W
個の数字はブロックの情報を表し, ハートマークのないブロックを表す '
0
', ハートマークのブロックを表す '
1
' から構成されます.
入力の終了は,
H
=
W
= 0 であるデータセットによって示されます. このケースに対して出力をしてはいけません.
1 ≤
H
,
W
≤ 12 であり、ハートマークのブロックの数は 6 個以下と仮定してかまいません.
Output
それぞれのデータセットに対して, 太郎君が食べられる最大のブロック数を出力してください.
Sample Input
4 4
1 0 0 0
0 0 1 0
0 1 0 0
1 0 0 1
1 1
1
2 3
1 0 0
0 0 1
0 0
Output for the Sample Input
7
0
2

Submitted solutions:

code_snippet: #line 2 "template.hpp"
// #pragma GCC target("avx2")
// #pragma GCC optimize("O3")
// #pragma GCC optimize("unroll-loops")

#include <bits/stdc++.h>
using namespace std;
// https://xn--kst.jp/blog/2019/08/29/cpp-comp/
// debug methods
// usage: debug(x,y);
// vector 出力できるように修正
template <typename T>
ostream& debug_print(ostream& os, const vector<T>& v) {
    os << "[";
    for (size_t i = 0; i < v.size(); ++i) {
        os << v[i];
        if (i < v.size() - 1) os << ", ";
    }
    os << "]";
    return os;
}
template <typename T>
ostream& debug_print(ostream& os, const T& var) {
    os << var;
    return os;
}
#define CHOOSE(a) CHOOSE2 a
#define CHOOSE2(a0, a1, a2, a3, a4, x, ...) x
#define debug_1(x1) { cout << #x1 << ": "; debug_print(cout, x1) << endl; }
#define debug_2(x1, x2) { cout << #x1 << ": "; debug_print(cout, x1) << ", " << #x2 << ": "; debug_print(cout, x2) << endl; }
#define debug_3(x1, x2, x3) { cout << #x1 << ": "; debug_print(cout, x1) << ", " << #x2 << ": "; debug_print(cout, x2) << ", " << #x3 << ": "; debug_print(cout, x3) << endl; }
#define debug_4(x1, x2, x3, x4) { cout << #x1 << ": "; debug_print(cout, x1) << ", " << #x2 << ": "; debug_print(cout, x2) << ", " << #x3 << ": "; debug_print(cout, x3) << ", " << #x4 << ": "; debug_print(cout, x4) << endl; }
#define debug_5(x1, x2, x3, x4, x5) { cout << #x1 << ": "; debug_print(cout, x1) << ", " << #x2 << ": "; debug_print(cout, x2) << ", " << #x3 << ": "; debug_print(cout, x3) << ", " << #x4 << ": "; debug_print(cout, x4) << ", " << #x5 << ": "; debug_print(cout, x5) << endl; }

#ifdef LOCAL
#define debug(...) CHOOSE((__VA_ARGS__, debug_5, debug_4, debug_3, debug_2, debug_1, ~))(__VA_ARGS__)
#else
#define debug(...)
#endif

using ll = long long;
using vl = vector<ll>;
using vll = vector<vl>;
using P = pair<ll, ll>;
#define all(v) v.begin(), v.end()
template <typename T> inline bool chmax(T &a, T b) {
    return ((a < b) ? (a = b, true) : (false));
}
template <typename T> inline bool chmin(T &a, T b) {
    return ((a > b) ? (a = b, true) : (false));
}
#define rep1(i, n) for(ll i = 1; i <= ((ll)n); ++i)
// https://trap.jp/post/1224/
template <class... T> constexpr auto min(T... a) {
    return min(initializer_list<common_type_t<T...>>{a...});
}
template <class... T> constexpr auto max(T... a) {
    return max(initializer_list<common_type_t<T...>>{a...});
}
template <class... T> void input(T &...a) { (cin >> ... >> a); }
template <class T> void input(vector<T> &a) {
    for(T &x : a)
        cin >> x;
}
void print() { cout << '\n'; }
template <class T, class... Ts> void print(const T &a, const Ts &...b) {
    cout << a;
    (cout << ... << (cout << ' ', b));
    cout << '\n';
}
void print(const string &s) {
    cout << s << '\n';
}
template <class Container, typename = void>
struct is_container : std::false_type {};
template <class Container>
struct is_container<Container, std::void_t<decltype(std::declval<Container>().begin()), decltype(std::declval<Container>().end())>> : std::true_type {};
template <class Container>
typename enable_if<is_container<Container>::value>::type print(const Container& x) {
    if (!x.empty()) {
        auto it = x.begin();
        for (; it != prev(x.end()); ++it) {
            cout << *it << " ";
        }
        cout << *it << "\n";  // 最後の要素を出力して改行
    }
}
#define INT(...)                                                               \
    int __VA_ARGS__;                                                           \
    input(__VA_ARGS__)
#define LL(...)                                                                \
    long long __VA_ARGS__;                                                     \
    input(__VA_ARGS__)
#define STR(...)                                                               \
    string __VA_ARGS__;                                                        \
    input(__VA_ARGS__)
#define REP1(a) for(ll i = 0; i < a; i++)
#define REP2(i, a) for(ll i = 0; i < a; i++)
#define REP3(i, a, b) for(ll i = a; i < b; i++)
#define REP4(i, a, b, c) for(ll i = a; i < b; i += c)
#define overload4(a, b, c, d, e, ...) e
#define rep(...) overload4(__VA_ARGS__, REP4, REP3, REP2, REP1)(__VA_ARGS__)

ll inf = 3e18;
vl dx = {1, -1, 0, 0};
vl dy = {0, 0, 1, -1};
#line 3 "graph/graph-template.hpp"
// https://ei1333.github.io/library/graph/graph-template.hpp
template <class T = ll> struct Edge {
    int from, to;
    T cost;
    int idx;
    Edge() = default;
    Edge(int from, int to, T cost = 1, int idx = -1)
        : from(from), to(to), cost(cost), idx(idx) {}
};
template <class T = ll> struct Graph {
    vector<vector<Edge<T>>> g;
    int es; // edge_size
    Graph(int n) : g(n), es(0) {};
    int size() const { return g.size(); }
    void add_directed_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es++);
    }
    void add_edge(int from, int to, T cost = 1) {
        g[from].emplace_back(from, to, cost, es);
        g[to].emplace_back(to, from, cost, es++);
    }
    vector<Edge<T>> &operator[](const int &k) { return g[k]; }
    const vector<Edge<T>> &operator[](const int &k) const { return g[k]; }
    void read(int m, int padding = -1, bool weighted = false,
              bool directed = false) {
        rep(i, m) {
            int a, b;
            T c(1);
            cin >> a >> b;
            a += padding;
            b += padding;
            if(weighted)
                cin >> c;
            if(directed)
                add_directed_edge(a, b, c);
            else
                add_edge(a, b, c);
        }
    }
};
#line 3 "graph/minimum-steiner-tree.hpp"
template <class T = ll> struct MinimumSteinerTree {
    int n, k;
    vector<int> terminal;
    T cost;
    const T infty = numeric_limits<T>::max();
    vector<vector<T>> dp;
    MinimumSteinerTree(const Graph<T> &g, const vector<int> terminal)
        : n(g.size()), k(terminal.size()), terminal(terminal), cost(0),
          dp(1 << k, vector<T>(n, infty)) {
        rep(i, k) {
            dp[1 << i][terminal[i]] = 0;
        }
        rep(bit, 1, 1 << k) {
            rep(i, n) {
                for(int sub = (bit - 1) & bit; sub > 0; sub = (sub - 1) & bit) {
                    if(dp[sub][i] != infty and dp[bit ^ sub][i] != infty)
                        chmin(dp[bit][i], dp[sub][i] + dp[bit ^ sub][i]);
                }
            }
            using pti = pair<T, int>;
            priority_queue<pti, vector<pti>, greater<pti>> pq;
            rep(i, n) pq.push(pti(dp[bit][i], i));
            while(pq.size()) {
                auto [c, v] = pq.top();
                pq.pop();
                if(c != dp[bit][v] or c == infty)
                    continue;
                for(auto &e : g[v]) {
                    T nc = c + e.cost;
                    if(chmin(dp[bit][e.to], nc))
                        pq.push(pti(nc, e.to));
                }
            }
        }
        cost = dp.back()[terminal.front()];
    }
};
#line 3 "/home/y_midori/cp/test3.cpp"
ll h, w;
void solve() {
    if(h == 0 and w == 0)
        exit(0);
    Graph<ll> g(h * w);
    rep(i, h) rep(j, w) {
        if(i + 1 < h)
            g.add_edge(i * w + j, (i + 1) * w + j);
        if(j + 1 < w)
            g.add_edge(i * w + j, i * w + j + 1);
    }
    vector<int> term;
    rep(i, h) rep(j, w) {
        INT(c);
        if(c)
            term.emplace_back(i * w + j);
    }
    MinimumSteinerTree<ll> mst(g, term);
    print(h * w - mst.cost - 1);
    // 木になるのでコスト(辺数)+1が頂点数
}
int main() {
    ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    // LL(t);
    while(cin >> h >> w)
        solve();
}
accuracy: 1
time_ms: 10
memory_kb: 3576
final_rank: 17

code_snippet: /*

  Problem F: Chocolate with Heart Marks

Taro loves chocolate, and when he gets home from school he eats his favorite chocolate bar with heart marks,
and his recent enjoyment is to eat all the heart mark blocks to the end.
Taro tries to eat as many heart marks as possible, leaving all the heart mark blocks connected.

 However, Taro is still young, and if you try to eat it like the one mentioned above,
 you'll end up with unnecessary blocks. So Taro asked you to create a program that will determine
 the maximum number of blocks you can eat when leaving all the heart-marked blocks connected.

Taro does not care how you eat as long as all the heart-marked blocks are connected. 
If one side of the block is not in contact with the other block, then it is divided.


Input

The input consists of multiple data sets. Each data set is given in the following format: 

 H and W are integers that represent the vertical and horizontal size of the chocolate bar, respectively. 
 H x W numbers represent information about the block, and ' 0 ', which represents a block without a heart mark, and ' 1 consist of ', which represents a block with a heart mark.

The end of the input is indicated by a dataset where H = W = 0. Do not output for this case.

It can be assumed that 1 <= H, W <= 12, and the number of heart mark blocks is less than or equal to 6. 

*/

// Remove aggressive optimization pragmas that cause conflicts with standard library
// #pragma GCC optimize("-O3,inline,unroll-all-loops,fast-math")
// #pragma GCC target("tune=native")
// #pragma GCC target("avx2")

// Replace bits/stdc++.h with specific standard headers
#include <algorithm>
#include <array>
#include <cassert>
#include <chrono>
#include <cmath>
#include <ctime>
#include <deque>
#include <functional>
#include <iostream>
#include <limits>
#include <map>
#include <numeric>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <tuple>
#include <type_traits>
#include <unordered_set>
#include <utility>
#include <vector>
#include <sys/time.h>
using namespace std;

// Macros

using i8 = int8_t;
using u8 = uint8_t;
using i16 = int16_t;
using u16 = uint16_t;
using i32 = int32_t;
using u32 = uint32_t;
using i64 = int64_t;
using u64 = uint64_t;
using f32 = float;
using f64 = double;

#define ALWAYS_INLINE __attribute__((always_inline))
#define FORCE_INLINE ALWAYS_INLINE inline

#define AS_STRING_IMPL(x) #x
#define AS_STRING(x) AS_STRING_IMPL(x)
#define runtime_assert(x)                                                                                                                                                                                                                      \
  do {                                                                                                                                                                                                                                         \
    if (!(x)) { throw runtime_error(__FILE__ ":" AS_STRING(__LINE__) " Assertion failed: " #x); }                                                                                                                                              \
  } while (0)
#define impossible()                                                                                                                                                                                                                           \
  do { throw runtime_error(__FILE__ ":" AS_STRING(__LINE__) " impossible"); } while (0)
#define all(x) begin(x), end(x)
#define pb push_back
#define eb emplace_back

// Types

template <class T>
using min_queue = priority_queue<T, vector<T>, greater<T>>;
template <class T>
using max_queue = priority_queue<T>;

// Printing

template <class T>
void print_collection(ostream& out, T const& x);

template <class T, size_t... I>
void print_tuple(ostream& out, T const& a, index_sequence<I...>);

namespace std {

template <class... A>
ostream& operator<<(ostream& out, tuple<A...> const& x) {
  print_tuple(out, x, index_sequence_for<A...>{});
  return out;
}
template <class... A>
ostream& operator<<(ostream& out, pair<A...> const& x) {
  print_tuple(out, x, index_sequence_for<A...>{});
  return out;
}

template <class A, size_t N>
ostream& operator<<(ostream& out, array<A, N> const& x) {
  print_collection(out, x);
  return out;
}
template <class A>
ostream& operator<<(ostream& out, vector<A> const& x) {
  print_collection(out, x);
  return out;
}
template <class A>
ostream& operator<<(ostream& out, deque<A> const& x) {
  print_collection(out, x);
  return out;
}
template <class A>
ostream& operator<<(ostream& out, multiset<A> const& x) {
  print_collection(out, x);
  return out;
}
template <class A, class B>
ostream& operator<<(ostream& out, multimap<A, B> const& x) {
  print_collection(out, x);
  return out;
}
template <class A>
ostream& operator<<(ostream& out, set<A> const& x) {
  print_collection(out, x);
  return out;
}
template <class A, class B>
ostream& operator<<(ostream& out, map<A, B> const& x) {
  print_collection(out, x);
  return out;
}
template <class A, class B>
ostream& operator<<(ostream& out, unordered_set<A> const& x) {
  print_collection(out, x);
  return out;
}

} // namespace std

template <class T, size_t... I>
void print_tuple(ostream& out, T const& a, index_sequence<I...>) {
  using swallow = int[];
  out << '(';
  (void)swallow{0, (void(out << (I == 0 ? "" : ", ") << get<I>(a)), 0)...};
  out << ')';
}

template <class T>
void print_collection(ostream& out, T const& x) {
  int f = 0;
  out << '[';
  for (auto const& i : x) {
    out << (f++ ? "," : "");
    out << i;
  }
  out << "]";
}

// Random

struct RNG {
  uint64_t s[2]{};

  explicit RNG(u64 seed) { reset(seed); }

  RNG() { reset(time(0)); }

  using result_type = u32;
  static constexpr u32 min() { return numeric_limits<u32>::min(); }
  static constexpr u32 max() { return numeric_limits<u32>::max(); }
  u32 operator()() { return randomInt32(); }

  static FORCE_INLINE uint64_t rotl(const uint64_t x, int k) { return (x << k) | (x >> (64 - k)); }

  inline void reset(u64 seed = time(nullptr)) {
    struct splitmix64_state {
      u64 s;

      u64 splitmix64() {
        u64 result = (s += 0x9E3779B97f4A7C15);
        result = (result ^ (result >> 30)) * 0xBF58476D1CE4E5B9;
        result = (result ^ (result >> 27)) * 0x94D049BB133111EB;
        return result ^ (result >> 31);
      }
    };

    splitmix64_state sm{seed};

    s[0] = sm.splitmix64();
    s[1] = sm.splitmix64();
  }

  uint64_t next() {
    const uint64_t s0 = s[0];
    uint64_t s1 = s[1];
    const uint64_t result = rotl(s0 * 5, 7) * 9;

    s1 ^= s0;
    s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
    s[1] = rotl(s1, 37);                   // c

    return result;
  }

  inline u32 randomInt32() { return next(); }

  inline u64 randomInt64() { return next(); }

  inline u32 random32(u32 r) { return (((u64)randomInt32()) * r) >> 32; }

  inline u64 random64(u64 r) { return randomInt64() % r; }

  inline u32 randomRange32(u32 l, u32 r) { return l + random32(r - l + 1); }

  inline u64 randomRange64(u64 l, u64 r) { return l + random64(r - l + 1); }

  inline double randomDouble() { return (double)randomInt32() / 4294967296.0; }

  inline float randomFloat() { return (float)randomInt32() / 4294967296.0; }

  inline double randomRangeDouble(double l, double r) { return l + randomDouble() * (r - l); }

  template <class T>
  void shuffle(vector<T>& v) {
    i32 sz = v.size();
    for (i32 i = sz; i > 1; i--) {
      i32 p = (i32)random32(i);
      swap(v[i - 1], v[p]);
    }
  }

  template <class T>
  void shuffle(T* fr, T* to) {
    i32 sz = distance(fr, to);
    for (int i = sz; i > 1; i--) {
      int p = (i32)random32(i);
      swap(fr[i - 1], fr[p]);
    }
  }

  template <class T>
  inline int sample_index(vector<T> const& v) {
    return random32(v.size());
  }

  template <class T>
  inline T sample(vector<T> const& v) {
    return v[sample_index(v)];
  }
} rng;

// Timer

struct timer {
  chrono::high_resolution_clock::time_point t_begin;

  timer() : t_begin(chrono::high_resolution_clock::now()) {}

  void reset() { t_begin = chrono::high_resolution_clock::now(); }

  [[nodiscard]] double elapsed() const { return chrono::duration<double>(chrono::high_resolution_clock::now() - t_begin).count(); }
};

// Util

template <class T>
T& smin(T& x, T const& y) {
  x = min(x, y);
  return x;
}

template <class T>
T& smax(T& x, T const& y) {
  x = max(x, y);
  return x;
}

template <typename T>
int sgn(T val) {
  if (val < 0) return -1;
  if (val > 0) return 1;
  return 0;
}

static inline string int_to_string(int val, int digits = 0) {
  string s = to_string(val);
  reverse(all(s));
  while ((int)s.size() < digits) s.pb('0');
  reverse(all(s));
  return s;
}

// Debug

static inline void debug_impl_seq() { cerr << "}"; }

template <class T, class... V>
void debug_impl_seq(T const& t, V const&... v) {
  cerr << t;
  if (sizeof...(v)) { cerr << ", "; }
  debug_impl_seq(v...);
}

#define debug(x...)                                                                                                                                                                                                                            \
  do {                                                                                                                                                                                                                                         \
    cerr << __FILE__ ":" AS_STRING(__LINE__) "  {" << #x << "} = {";                                                                                                                                                                           \
    debug_impl_seq(x);                                                                                                                                                                                                                         \
    cerr << endl << flush;                                                                                                                                                                                                                     \
  } while (0)

#define nl '\n'
using ll = long long;

const ll infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

inline bool has_bit_set(const i32 x, const i32 id) { return (x & (1 << id)) != 0; }
inline void set_bit(i32& x, const i32 id) { x |= (1 << id); }
inline void unset_bit(i32 &x, const i32 id){ x &= ~(1 << id); }

template <typename T1, typename T2>
istream& operator>>(istream& is, pair<T1, T2>& p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
istream& operator>>(istream& is, vector<T>& v) {
  for (T& in : v) is >> in;
  return is;
}

template <typename T = ll>
vector<T> make_v(size_t a) {
  return vector<T>(a);
}

template <typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template <typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(T& t, const V& v) {
  t = v;
}

template <typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(T& t, const V& v) {
  for (auto& e : t) fill_v(e, v);
}

template <class T>
inline void remove_one(vector<T>& data, T x) {
  data.erase(find(data.begin(), data.end(), x));
}

template <typename T>
struct Edge {
  int from, to;
  T cost;
  int idx;

  Edge() = default;

  Edge(int from, int to, T cost = 1, int idx = -1) : from(from), to(to), cost(cost), idx(idx) {}

  operator int() const { return to; }
};

template <typename T = int>
struct Graph {
  vector<vector<Edge<T>>> g;
  int es;

  Graph() = default;

  explicit Graph(int n) : g(n), es(0) {}

  size_t size() const { return g.size(); }

  void add_directed_edge(int from, int to, T cost = 1) { g[from].emplace_back(from, to, cost, es++); }

  void add_edge(int from, int to, T cost = 1) {
    g[from].emplace_back(from, to, cost, es);
    g[to].emplace_back(to, from, cost, es++);
  }

  void read(int M, int padding = -1, bool weighted = false, bool directed = false) {
    for (int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      a += padding;
      b += padding;
      T c = T(1);
      if (weighted) cin >> c;
      if (directed)
        add_directed_edge(a, b, c);
      else
        add_edge(a, b, c);
    }
  }

  inline vector<Edge<T>>& operator[](const int& k) { return g[k]; }

  inline const vector<Edge<T>>& operator[](const int& k) const { return g[k]; }
};

template <typename T = int>
using Edges = vector<Edge<T>>;


template <typename T>
struct MinimumSteinerTree {
  using pi = pair<int, int>;

  const T infty = numeric_limits<T>::max();

  vector<vector<T> > dp;
  T cost;

  MinimumSteinerTree() = default;

  explicit MinimumSteinerTree(const Graph<T> &g, const vector<int> &terminal)
      : g(g),
        terminal(terminal),
        dp(1 << terminal.size(), vector<T>(g.size(), infty)),
        pre(1 << terminal.size(), vector<pi>(g.size(), pi(-1, -1))) {
    assert(not terminal.empty());
    const int n = (int)g.size(), t = (int)terminal.size();
    for (int i = 0; i < t; i++) {
      assert(0 <= terminal[i] and terminal[i] < n);
      dp[1 << i][terminal[i]] = 0;
    }
    using qt = pair<T, int>;
    priority_queue<qt, vector<qt>, greater<> > que;
    for (int i = 1; i < (1 << t); i++) {
      for (int j = 0; j < n; j++) {
        for (int k = i; k > 0; k = (k - 1) & i) {
          if (dp[k][j] != infty and dp[i ^ k][j] != infty) {
            T nxt = dp[k][j] + dp[i ^ k][j];
            if (nxt < dp[i][j]) {
              dp[i][j] = nxt;
              pre[i][j] = {k, -1};
            }
          }
        }
      }
      for (int j = 0; j < n; j++) {
        if (dp[i][j] != infty) {
          que.emplace(dp[i][j], j);
        }
      }
      while (not que.empty()) {
        auto [now, v] = que.top();
        que.pop();
        if (dp[i][v] < now) continue;
        for (int j = 0; j < (int)g[v].size(); j++) {
          const auto &e = g[v][j];
          if (now + e.cost < dp[i][e.to]) {
            dp[i][e.to] = now + e.cost;
            pre[i][e.to] = {v, j};
            que.emplace(dp[i][e.to], e.to);
          }
        }
      }
    }
    cost = dp[(1 << t) - 1][terminal[0]];
  }

  Edges<T> restore() const {
    const int t = (int)terminal.size();
    assert(dp[(1 << t) - 1][terminal[0]] != infty);
    Edges<T> tree;
    vector<pair<int, int> > st;
    st.emplace_back((1 << t) - 1, terminal[0]);
    while (not st.empty()) {
      auto [x, y] = st.back();
      st.pop_back();
      if (pre[x][y].second == -1) {
        if (pre[x][y].first != -1) {
          st.emplace_back(pre[x][y].first, y);
          st.emplace_back(x ^ pre[x][y].first, y);
        }
      } else {
        tree.emplace_back(g[pre[x][y].first][pre[x][y].second]);
        st.emplace_back(x, pre[x][y].first);
      }
    }
    return tree;
  }

 private:
  const Graph<T> &g;
  const vector<int> &terminal;
  vector<vector<pi> > pre;
};


int main() {
  int H, W;
  while (cin >> H >> W, H) {
    Graph<int> g(H * W);
    vector<int> terminal;
    for (int i = 0; i < H; i++) {
      for (int j = 0; j < W; j++) {
        int t;
        cin >> t;
        if (i > 0) { g.add_edge(i * W + j, i * W + j - W, 1); }
        if (j > 0) { g.add_edge(i * W + j, i * W + j - 1, 1); }
        if (t == 1) { terminal.emplace_back(i * W + j); }
      }
    }
    cout << H * W - MinimumSteinerTree(g, terminal).cost - 1 << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3512
final_rank: 11

code_snippet: #include<bits/stdc++.h>
#if __has_include(<atcoder/all>)
#include<atcoder/all>
#endif

using namespace std;
using int64 = long long;

const int64 infll = (1LL << 62) - 1;
const int inf = (1 << 30) - 1;

struct IoSetup {
  IoSetup() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
    cerr << fixed << setprecision(10);
  }
} iosetup;

template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &p) {
  os << p.first << " " << p.second;
  return os;
}

template<typename T1, typename T2>
istream &operator>>(istream &is, pair<T1, T2> &p) {
  is >> p.first >> p.second;
  return is;
}

template<typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  for (int i = 0; i < (int) v.size(); i++) {
    os << v[i] << (i + 1 != v.size() ? " " : "");
  }
  return os;
}

template<typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (T &in : v) is >> in;
  return is;
}

template<typename T1, typename T2>
inline bool chmax(T1 &a, T2 b) { return a < b && (a = b, true); }

template<typename T1, typename T2>
inline bool chmin(T1 &a, T2 b) { return a > b && (a = b, true); }

template<typename T = int64>
vector<T> make_v(size_t a) {
  return vector<T>(a);
}

template<typename T, typename... Ts>
auto make_v(size_t a, Ts... ts) {
  return vector<decltype(make_v<T>(ts...))>(a, make_v<T>(ts...));
}

template<typename T, typename V>
typename enable_if<is_class<T>::value == 0>::type fill_v(T &t, const V &v) {
  t = v;
}

template<typename T, typename V>
typename enable_if<is_class<T>::value != 0>::type fill_v(T &t, const V &v) {
  for (auto &e : t) fill_v(e, v);
}

template<typename F>
struct FixPoint : F {
  explicit FixPoint(F &&f) : F(std::forward<F>(f)) {}

  template<typename... Args>
  decltype(auto) operator()(Args &&... args) const {
    return F::operator()(*this, std::forward<Args>(args)...);
  }
};

template<typename F>
inline decltype(auto) MFP(F &&f) {
  return FixPoint<F>{std::forward<F>(f)};
}

#line 2 "graph/graph-template.hpp"

template<typename T = int>
struct Edge {
  int from, to;
  T cost;
  int idx;

  Edge() = default;

  Edge(int from, int to, T cost = 1, int idx = -1)
      : from(from), to(to), cost(cost), idx(idx) {}

  operator int() const { return to; }
};

template<typename T = int>
struct Graph {
  vector<vector<Edge<T> > > g;
  int es;

  Graph() = default;

  explicit Graph(int n) : g(n), es(0) {}

  size_t size() const { return g.size(); }

  void add_directed_edge(int from, int to, T cost = 1) {
    g[from].emplace_back(from, to, cost, es++);
  }

  void add_edge(int from, int to, T cost = 1) {
    g[from].emplace_back(from, to, cost, es);
    g[to].emplace_back(to, from, cost, es++);
  }

  void read(int M, int padding = -1, bool weighted = false,
            bool directed = false) {
    for (int i = 0; i < M; i++) {
      int a, b;
      cin >> a >> b;
      a += padding;
      b += padding;
      T c = T(1);
      if (weighted) cin >> c;
      if (directed)
        add_directed_edge(a, b, c);
      else
        add_edge(a, b, c);
    }
  }

  inline vector<Edge<T> > &operator[](const int &k) { return g[k]; }

  inline const vector<Edge<T> > &operator[](const int &k) const { return g[k]; }
};

template<typename T = int>
using Edges = vector<Edge<T> >;

template<typename T>
struct MinimumSteinerTree {
  using pi = pair<int, int>;

  const T infty = numeric_limits<T>::max();

  vector<vector<T> > dp;
  T cost;

  MinimumSteinerTree() = default;

  explicit MinimumSteinerTree(const Graph<T> &g, const vector<int> &terminal)
      : g(g),
        terminal(terminal),
        dp(1 << terminal.size(), vector<T>(g.size(), infty)),
        pre(1 << terminal.size(), vector<pi>(g.size(), pi(-1, -1))) {
    assert(not terminal.empty());
    const int n = (int) g.size(), t = (int) terminal.size();
    for (int i = 0; i < t; i++) {
      assert(0 <= terminal[i] and terminal[i] < n);
      dp[1 << i][terminal[i]] = 0;
    }
    using qt = pair<T, int>;
    priority_queue<qt, vector<qt>, greater<> > que;
    for (int i = 1; i < (1 << t); i++) {
      for (int j = 0; j < n; j++) {
        for (int k = i; k > 0; k = (k - 1) & i) {
          if (dp[k][j] != infty and dp[i ^ k][j] != infty) {
            T nxt = dp[k][j] + dp[i ^ k][j];
            if (nxt < dp[i][j]) {
              dp[i][j] = nxt;
              pre[i][j] = {k, -1};
            }
          }
        }
      }
      for (int j = 0; j < n; j++) {
        if (dp[i][j] != infty) {
          que.emplace(dp[i][j], j);
        }
      }
      while (not que.empty()) {
        auto [now, v] = que.top();
        que.pop();
        if (dp[i][v] < now) continue;
        for (int j = 0; j < (int) g[v].size(); j++) {
          const auto &e = g[v][j];
          if (now + e.cost < dp[i][e.to]) {
            dp[i][e.to] = now + e.cost;
            pre[i][e.to] = {v, j};
            que.emplace(dp[i][e.to], e.to);
          }
        }
      }
    }
    cost = dp[(1 << t) - 1][terminal[0]];
  }

  Edges<T> restore() const {
    const int t = (int) terminal.size();
    assert(dp[(1 << t) - 1][terminal[0]] != infty);
    Edges<T> tree;
    vector<pair<int, int> > st;
    st.emplace_back((1 << t) - 1, terminal[0]);
    while (not st.empty()) {
      auto [x, y] = st.back();
      st.pop_back();
      if (pre[x][y].second == -1) {
        if (pre[x][y].first != -1) {
          st.emplace_back(pre[x][y].first, y);
          st.emplace_back(x ^ pre[x][y].first, y);
        }
      } else {
        tree.emplace_back(g[pre[x][y].first][pre[x][y].second]);
        st.emplace_back(x, pre[x][y].first);
      }
    }
    return tree;
  }

 private:
  const Graph<T> &g;
  const vector<int> &terminal;
  vector<vector<pi> > pre;
};

int main() {
  int H, W;
  while(cin >> H >> W, H) {
    Graph< int > g(H * W);
    vector< int > terminal;
    for(int i = 0; i < H; i++) {
      for(int j = 0; j < W; j++) {
        int t;
        cin >> t;
        if(i > 0) {
          g.add_edge(i * W + j, i * W + j - W, 1);
        }
        if(j > 0) {
          g.add_edge(i * W + j, i * W + j - 1, 1);
        }
        if(t == 1) {
          terminal.emplace_back(i * W + j);
        }
      }
    }
    cout << H * W - MinimumSteinerTree(g, terminal).cost - 1 << endl;
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3560
final_rank: 16

code_snippet: #define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=1040"

// #include "../../graph/edge.cpp"
// #include "../../graph/minimum_steiner_tree.hpp"

#include <bits/stdc++.h>
using namespace std;

template <typename T>
struct Edge {
    int from, to;
    T weight;
    Edge() = default;
    Edge(int to, T weight) : from(-1), to(to), weight(weight) {}
    Edge(int from, int to, T weight) : from(from), to(to), weight(weight) {}
};

template <typename T>
T minimum_steiner_tree(std::vector<std::vector<Edge<T>>>& G, std::vector<int>& terminals) {
    const int n = G.size();
    const int t = terminals.size();
    constexpr T INF = std::numeric_limits<T>::max() / 2;
    using P = std::pair<T, int>;

    std::vector<std::vector<T>> dp(1 << t, std::vector<T>(n, INF));
    for (int i = 0; i < t; ++i) dp[1 << i][terminals[i]] = 0;

    for (int S = 1; S < (1 << t); ++S) {
        for (int i = 0; i < n; ++i) {
            for (int U = S; U > 0; U = (U - 1) & S) {
                dp[S][i] = std::min(dp[S][i], dp[S ^ U][i] + dp[U][i]);
            }
        }
        if (S == (1 << t) - 1) continue;
        std::priority_queue<P, std::vector<P>, std::greater<>> pq;
        for (int i = 0; i < n; ++i) {
            pq.emplace(dp[S][i], i);
        }
        while (!pq.empty()) {
            auto [d, v] = pq.top();
            pq.pop();
            if (dp[S][v] < d) continue;
            for (auto& e : G[v]) {
                if (dp[S][e.to] > d + e.weight) {
                    dp[S][e.to] = d + e.weight;
                    pq.emplace(dp[S][e.to], e.to);
                }
            }
        }
    }

    return dp.back()[terminals[0]];
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);

    while (true) {
        int H, W;
        cin >> H >> W;
        if (H == 0) break;
        vector<vector<Edge<int>>> G(H*W);
        vector<int> terminals;
        for (int i = 0; i < H; ++i) {
            for (int j = 0; j < W; ++j) {
                int s;
                cin >> s;
                if (s) terminals.push_back(i*W+j);
                if (i < H-1) {
                    G[i*W+j].push_back({(i+1)*W+j, 1});
                    G[(i+1)*W+j].push_back({i*W+j, 1});
                }
                if (j < W-1) {
                    G[i*W+j].push_back({i*W+j+1, 1});
                    G[i*W+j+1].push_back({i*W+j, 1});
                }
            }
        }
        cout << H*W - minimum_steiner_tree(G, terminals) - 1 << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3432
final_rank: 7

code_snippet: #include <algorithm>
#include <cassert>
#include <iomanip>
#include <queue>
#include <iostream>
#include <vector>

#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)
#define DEBUGP(val) cerr << #val << "=" << val << "\n"

using namespace std;
typedef long long int ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef pair<int, int> PI;


const int inf = 1e9;
// Dreyfus-Wagner. O(4^k)
// https://kopricky.github.io/code/Academic/steiner_tree.html
int steiner_tree(const vector<vector<PI> > &g, const VI &term) {
  int n = g.size();
  int k = term.size();
  vector<vector<int> > dp(n, vector<int>(1 << k, inf));
  // base case: |bits| = 1
  REP(i, 0, k) {
    dp[term[i]][1 << i] = 0;
  }
  REP(bits, 1, 1 << k) {
    REP(i, 0, n) {
      REP(sub, 1, bits) {
        if ((sub & bits) != sub) continue;
        dp[i][bits] = min(dp[i][bits], dp[i][sub] + dp[i][bits - sub]);
      }
    }
    priority_queue<PI, vector<PI>, greater<PI> > que;
    REP(i, 0, n) {
      if (dp[i][bits] < inf) {
        que.push(PI(dp[i][bits], i));
        dp[i][bits] = inf;
      }
    }
    while (not que.empty()) {
      PI dv = que.top(); que.pop();
      int d = dv.first;
      int v = dv.second;
      if (dp[v][bits] <= d) continue;
      dp[v][bits] = d;
      REP(j, 0, g[v].size()) {
        PI wc = g[v][j];
        int w = wc.first;
        int c = wc.second;
        que.push(PI(d + c, w));
      }
    }
  }
  int mi = inf;
  REP(i, 0, n) {
    mi = min(mi, dp[i][(1 << k) - 1]);
  }
  return mi;   
}

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int h, w;
  while(cin >> h >> w && h && w) {
    vector<VI> s(h, VI(w));
    REP(i, 0, h) {
      REP(j, 0, w) {
        cin >> s[i][j];
      }
    }
    vector<vector<PI> > g(h * w);
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};
    VI term;
    REP(i, 0, h) {
      REP(j, 0, w) {
        int v = i * w + j;
        if (s[i][j] == 1) term.push_back(v);
        REP(d, 0, 4) {
          int nx = i + dx[d];
          int ny = j + dy[d];
          if (nx < 0 || nx >= h || ny < 0 || ny >= w) continue;
          int u = nx * w + ny;
          g[v].push_back(PI(u, 1));
        }
      }
    }
    cout << h * w - 1 - steiner_tree(g, term) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 3184
final_rank: 8

code_snippet: #include <algorithm>
#include <cassert>
#include <iomanip>
#include <iostream>
#include <vector>

#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)
#define DEBUGP(val) cerr << #val << "=" << val << "\n"

using namespace std;
typedef long long int ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef pair<int, int> PI;


const int inf = 1e9;
// Dreyfus-Wagner. O(4^k)
int steiner_tree(const vector<vector<PI> > &g, const VI &term) {
  int n = g.size();
  int k = term.size();
  vector<vector<int> > dist(n, vector<int>(n, inf));
  REP(i, 0, n) {
    REP(j, 0, g[i].size()) {
      PI wc = g[i][j];
      int w = wc.first, c = wc.second;
      dist[i][w] = min(dist[i][w], c);
    }
  }
  REP(i, 0, n) dist[i][i] = 0;
  REP(l, 0, n) {
    REP(i, 0, n) {
      REP(j, 0, n) {
        dist[i][j] = min(dist[i][j], dist[i][l] + dist[l][j]);
      }
    }
  }
  vector<vector<int> > dp(n, vector<int>(1 << k, inf));
  // base case: |bits| = 1
  REP(i, 0, k) {
    REP(j, 0, n) {
      dp[j][1 << i] = min(dp[j][1 << i], dist[term[i]][j]);
    }
  }
  REP(bits, 1, 1 << k) {
    // if popcount(bits) == 1 then skip
    if ((bits & -bits) == bits) continue;
    REP(i, 0, n) {
      REP(sub, 1, bits) {
        if ((sub & bits) != sub) continue;
        dp[i][bits] = min(dp[i][bits], dp[i][sub] + dp[i][bits - sub]);
      }
    }
    REP(i, 0, n) {
      REP(j, 0, n) {
        dp[i][bits] = min(dp[i][bits], dp[j][bits] + dist[i][j]);
      }
    }
  }
  int mi = inf;
  REP(i, 0, n) {
    mi = min(mi, dp[i][(1 << k) - 1]);
  }
  return mi;   
}

int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int h, w;
  while(cin >> h >> w && h && w) {
    vector<VI> s(h, VI(w));
    REP(i, 0, h) {
      REP(j, 0, w) {
        cin >> s[i][j];
      }
    }
    vector<vector<PI> > g(h * w);
    int dx[4] = {1, 0, -1, 0};
    int dy[4] = {0, 1, 0, -1};
    VI term;
    REP(i, 0, h) {
      REP(j, 0, w) {
        int v = i * w + j;
        if (s[i][j] == 1) term.push_back(v);
        REP(d, 0, 4) {
          int nx = i + dx[d];
          int ny = j + dy[d];
          if (nx < 0 || nx >= h || ny < 0 || ny >= h) continue;
          int u = nx * w + ny;
          g[v].push_back(PI(u, 1));
          g[u].push_back(PI(v, 1));
        }
      }
    }
    cout << h * w - 1 - steiner_tree(g, term) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 3272
final_rank: 13

code_snippet: // includes
#include <bits/stdc++.h>
using namespace std;

// macros
#define pb emplace_back
#define mk make_pair
#define FOR(i, a, b) for(int i=(a);i<(b);++i)
#define rep(i, n) FOR(i, 0, n)
#define rrep(i, n) for(int i=((int)(n)-1);i>=0;i--)
#define irep(itr, st) for(auto itr = (st).begin(); itr != (st).end(); ++itr)
#define irrep(itr, st) for(auto itr = (st).rbegin(); itr != (st).rend(); ++itr)
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define UNIQUE(v) v.erase(unique(v.begin(), v.end()), v.end())
#define bit(n) (1LL<<(n))
// functions
template <class T>bool chmax(T &a, const T &b){if(a < b){a = b; return 1;} return 0;}
template <class T>bool chmin(T &a, const T &b){if(a > b){a = b; return 1;} return 0;}
template <typename T> istream &operator>>(istream &is, vector<T> &vec){for(auto &v: vec)is >> v; return is;}
template <typename T> ostream &operator<<(ostream &os, const vector<T>& vec){for(int i = 0; i < vec.size(); i++){ os << vec[i]; if(i + 1 != vec.size())os << " ";} return os;}
template <typename T> ostream &operator<<(ostream &os, const set<T>& st){for(auto itr = st.begin(); itr != st.end(); ++itr){ os << *itr; auto titr = itr; if(++titr != st.end())os << " ";} return os;}
template <typename T> ostream &operator<<(ostream &os, const unordered_set<T>& st){for(auto itr = st.begin(); itr != st.end(); ++itr){ os << *itr; auto titr = itr; if(++titr != st.end())os << " ";} return os;}
template <typename T> ostream &operator<<(ostream &os, const multiset<T>& st){for(auto itr = st.begin(); itr != st.end(); ++itr){ os << *itr; auto titr = itr; if(++titr != st.end())os << " ";} return os;}
template <typename T> ostream &operator<<(ostream &os, const unordered_multiset<T>& st){for(auto itr = st.begin(); itr != st.end(); ++itr){ os << *itr; auto titr = itr; if(++titr != st.end())os << " ";} return os;}
template <typename T1, typename T2> ostream &operator<<(ostream &os, const pair<T1, T2> &p){os << p.first << " " << p.second; return os;}
template <typename T1, typename T2> ostream &operator<<(ostream &os, const map<T1, T2> &mp){for(auto itr = mp.begin(); itr != mp.end(); ++itr){ os << itr->first << ":" << itr->second; auto titr = itr; if(++titr != mp.end())os << " "; } return os;}
template <typename T1, typename T2> ostream &operator<<(ostream &os, const unordered_map<T1, T2> &mp){for(auto itr = mp.begin(); itr != mp.end(); ++itr){ os << itr->first << ":" << itr->second; auto titr = itr; if(++titr != mp.end())os << " "; } return os;}
//  types
using ll = long long int;
using P = pair<int, int>;
// constants
const int inf = 1e9;
const ll linf = 1LL << 50;
const double EPS = 1e-10;
const int mod = 1000000007;
const int dx[4] = {-1, 0, 1, 0};
const int dy[4] = {0, -1, 0, 1};
// io
struct fast_io{
  fast_io(){ios_base::sync_with_stdio(false); cin.tie(0); cout << fixed << setprecision(20);}
} fast_io_;

template <typename T>
struct Graph {
  int n;
  vector<vector<T> > d;
  vector<vector<int> > path;
  Graph(int n): n(n) {
    d = vector<vector<T>>(n, vector<T>(n, numeric_limits<T>::max() / 10));
    path = vector<vector<int>>(n, vector<int>(n, -1));
    for(int i = 0; i < n; i++)d[i][i] = 0;
  }
  void warshall_floyd(){
    for(int k = 0; k < n; k++){
      for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
          if(d[i][j] > d[i][k] + d[k][j]){
            d[i][j] = d[i][k] + d[k][j];
            path[i][j] = k;
          }
        }
      }
    }
  }
  void adde(int at, int to, T cost){
    d[at][to] = cost;
  }
  vector<T>& operator[](size_t i){
    return d[i];
  }
};

using GraphI = Graph<int>;
using GraphL = Graph<ll>;

template <typename T>
struct SteinerTree{
  int n;
  vector<vector<T>> d;
  T inf = numeric_limits<T>::max() / 10;
  explicit SteinerTree(int n): n(n){
    d.resize(n, vector<T>(n, inf));
    for(int i = 0; i < n; i++)d[i][i] = 0;
  }
  void adde(int from, int to, T cost){
    d[from][to] = min(d[from][to], cost);
  }
  T steiner_tree(const vector<int> &v){
    if(v.size() == 1)return 0;
    // warshall floyd
    Graph<T> g(n);
    for(int i = 0; i < n; i++){
      for(int j = 0; j < n; j++){
        if(i != j && d[i][j] != inf)g.adde(i, j, d[i][j]);
      }
    }
    g.warshall_floyd();

    int t = v.size();
    vector<vector<T>> opt(1 << t, vector<T>(n, inf));
    for(int i = 0; i < t; i++){
      for(int j = 0; j < n; j++){
        opt[1 << i][j] = g.d[v[i]][j];
      }
    }

    for(int s = 0; s < (1 << t); s++){
      if(!(s & (s - 1)))continue;
      for(int p = 0; p < n; p++){
        for(int u = s; ; u = (u - 1) & s){
          opt[s][p] = min(opt[s][p], opt[u][p] + opt[s - u][p]);
          if(u == 0)break;
        }
      }
      for(int p = 0; p < n; p++){
        for(int q = 0; q < n; q++){
          opt[s][p] = min(opt[s][p], opt[s][q] + g.d[p][q]);
        }
      }
    }
    T res = inf;
    for(int s = 0; s < (1 << t); s++){
      for(int p = 0; p < n; p++){
        res = min(res, opt[s][p] + opt[(1<<t)-1-s][p]);
      }
    }
    return res;
  }
};

int c[12][12];

int main(int argc, char const* argv[])
{
  int h, w;
  while(true){
    cin >> h >> w;
    if(h == 0 && w == 0)break;
    SteinerTree<int> st(h * w);
    vector<int> v;
    rep(i, h){
      rep(j, w){
        cin >> c[i][j];
        if(c[i][j] == 1)v.pb(i * w + j);
      }
    }
    rep(i, h){
      rep(j, w){
        rep(k, 4){
          int nx = i + dx[k];
          int ny = j + dy[k];
          if(nx >= 0 && nx < h && ny >= 0 && ny < w){
            st.adde(i * w + j, nx * w + ny, 1);
          }
        }
      }
    }
    int res = h * w - st.steiner_tree(v) - 1;
    cout << res << endl;
  }
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3280
final_rank: 14

code_snippet: #include "bits/stdc++.h"

#pragma warning(disable:4996)
using namespace std;
using ld = long double;

namespace shniter {
	using Value=int;
	using Edge=pair<int,Value>;
	using Graph=vector<vector<Edge>>;
	const Value inf = 1<<20;

	vector<vector<Value>>w_h(const Graph&g) {
		vector<vector<Value>>asps(g.size(),vector<Value>(g.size(),1e9));
		for (int i = 0; i < g.size(); ++i) {
			for (auto e : g[i]) {
				asps[i][e.first]=e.second;
			}
			asps[i][i]=0;
		}

		for (int k = 0; k < g.size(); ++k) {
			for (int i = 0; i < g.size(); ++i) {
				for (int j = 0; j < g.size(); ++j) {
					asps[i][j]=min(asps[i][k]+asps[k][j],asps[i][j]);
				}
			}
		}
		return asps;
	}

	//最小シュナイター木
	Value solve(const Graph&g, const vector<int>shs) {
		//全点対最短経路(APSP : all pair shortest paths)
		auto asps = w_h(g);
		vector<vector<Value>>OPT(1 << shs.size(), vector<Value>(g.size(), inf));


		for (int p = 0; p < shs.size(); ++p) // trivial case
			for (int q = 0; q < g.size(); ++q){
				OPT[1 << p][q] = asps[shs[p]][q];
				OPT[0][q] = 0;
			}


		for (int k = 1; k < (1 << shs.size()); ++k) {
			for (int root = 0; root < g.size(); ++root) {
				if(!(k&(k-1)))continue;

				for (int e = 0; e < k; ++e) {
					if ((e | k) == k) {
						OPT[k][root] = min(OPT[k][root], OPT[e][root] + OPT[e^k][root]);
					}
				}
				
			}

			for (int p = 0; p < g.size(); ++p) {
				for (int q = 0; q < g.size(); ++q) {
					OPT[k][p] = min(OPT[k][p],
						OPT[k][q] + asps[p][q]);
				}
			}
		}
		Value ans = inf;
		for (int S = 0; S < (1 << shs.size()); ++S)
			for (int q = 0; q < g.size(); ++q)
				ans = min(ans, OPT[S][q] + OPT[((1 <<shs.size())-1 - S)][q]);

		return ans;
	}
}
int H,W;
int get_id(int x, int y) {
	if(x<0||W<=x||y<0||y>=H)return -1;
	else return y*W+x;
}

int main() {
	while (true) {
		cin>>H>>W;
		if(!H)break;
		vector<vector<int>>field(H,vector<int>(W));
		vector<int>storoberry_ids;
		for (int i = 0; i < H; ++i) {
			for (int j = 0; j < W; ++j) {
				cin>>field[i][j];
				if (field[i][j]) {
					storoberry_ids.push_back(get_id(j,i));
				}
			}
		}
		using namespace shniter;
		Graph g(H*W);
		for (int y = 0; y < H; ++y) {
			for (int x = 0; x < W; ++x) {
				for (int way = 0; way < 4; ++way) {
					int dx[] = { -1,0,1,0 };
					int dy[] = { 0,1,0,-1 };
					int nx=x+dx[way];
					int ny=y+dy[way];
					int nid=get_id(nx,ny);
					int id=get_id(x,y);
					if (nid != -1) {
						g[id].push_back(Edge(nid,1));
					}
				}
			}
		}
		Value answer=solve(g,storoberry_ids);
		cout<<H*W-(answer+1)<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3212
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
#define REP(i,a,n) for(int i=a;i<n;i++)
#define mat vector<vector<int> >
struct Minimum_Steiner_Tree{
	mat V;
	vector<int>T;
	int n,numT,Inf=1e8;
	Minimum_Steiner_Tree(int sz):n(sz),numT(0),V(sz,vector<int>(sz)){
		REP(i,0,sz)REP(j,0,sz)V[i][j]=(i==j?0:Inf);
	}
	void add_edge(int a,int b,int c){ V[a][b]=V[b][a]=c; }
	void add_vertex(int a){ T.push_back(a); numT++;}
	int build(){
		if(numT<=1)return 0;
		mat d(V);
		REP(k,0,n)REP(i,0,n)REP(j,0,n)d[i][j]=min( d[i][j], d[i][k] + d[k][j] );
		int OPT[(1<<numT)][n];
		REP(i,0,(1<<numT))REP(j,0,n)OPT[i][j]=Inf;
		REP(i,0,numT)REP(j,0,n)OPT[1<<i][j]=d[T[i]][j];
		REP(S,1,(1<<numT))if(S&(S-1)){
			REP(i,0,n)REP(j,0,S)if((S|j)==S) OPT[S][i] = min( OPT[S][i], OPT[j][i] + OPT[S-j][i] );
			REP(i,0,n)REP(j,0,n) OPT[S][i] = min( OPT[S][i], OPT[S][j] + d[i][j] );
		}
		int ans=Inf;
		REP(i,0,(1<<numT))REP(j,0,n)ans = min(ans, OPT[i][j] + OPT[((1 << numT)-1)-i][j]);
		return n-ans-1;
	}
};
int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};
int main(){
	int h,w,t;
	while(cin>>h>>w,h){
		Minimum_Steiner_Tree M(h*w);
		REP(i,0,h)REP(j,0,w){
			cin>>t;
			if(t)M.add_vertex(i*w+j);
			REP(k,0,4){
				int y=i+dy[k];
				int x=j+dx[k];
				if(y<0||x<0||y>=h||x>=w)continue;
				M.add_edge(i*w+j,y*w+x,1);
			}
		}
		cout<<M.build()<<endl;
	}
}
accuracy: 1
time_ms: 50
memory_kb: 3328
final_rank: 19

code_snippet: #include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using G=vector<vector<int>>;

int Dreyfus_wagner(const G &graph,const auto &term){
	using W=int; W inf=1<<28;
	const int n=int(graph.size()),t=int(term.size());
	if(t<=1) return 0;
	auto dist=graph;
	vector<vector<W>> opt(1<<t,vector<W>(n,inf));

	rep(k,n)rep(i,n)rep(j,n) chmin(dist[i][j],dist[i][k]+dist[k][j]);
	
	map<int,int> dict;
	rep(i,t){
		dict[term[i]]=1<<i;
		rep(j,n) opt[1<<i][j]=dist[term[i]][j];
		rep(j,t) opt[(1<<i)|(1<<j)][term[j]]=dist[term[i]][term[j]];
	}

	auto next_combination=[&](int s){
		int x=s&-s,y=s+x;
		return ((s&~y)/x>>1)|y;
    };

	rep(k,2,t){
		for(int s=(1<<k)-1;s<(1<<t);s=next_combination(s)){
			rep(i,n){
				int ns=s|dict[i];
				if(dict[i] and s==ns) continue;
				for(int u=(s-1)&s;u!=0;u=(u-1)&s){
					int c=s&(~u);
					chmin(opt[ns][i],opt[u][i]+opt[c][i]);
				}
			}
		}
		for(int s=(1<<k)-1;s<(1<<t);s=next_combination(s)){
			rep(i,n){
				int ns=s|dict[i];
				if(dict[i] and s==ns) continue;
				rep(j,n) chmin(opt[ns][i],opt[s][j]+dist[j][i]);
			}
		}
	}

	const int mask=(1<<t)-1;
	W ans=opt[mask][0];
	rep(i,n) chmin(ans,opt[mask][i]);
	return ans;
}

int main(void){
	int h,w;
	while(cin >> h >> w){
		if(h==0) break;
		const int inf=1<<28;

		G graph(h*w,vector<int>(h*w,inf));
		rep(i,h*w) graph[i][i]=0;
		vector<int> term;

		rep(i,h*w){
			int in;
			cin >> in;
			if(in) term.push_back(i);
		}
		
		rep(i,h)rep(j,w){
			const int cur=w*i+j;
			if(i+1<h) graph[cur][cur+w]=graph[cur+w][cur]=1;
			if(j+1<w) graph[cur][cur+1]=graph[cur+1][cur]=1;
		}
		int res=Dreyfus_wagner(graph,term);
		cout << h*w-1-res << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3260
final_rank: 18

code_snippet: #include <bits/stdc++.h>

#define _overload(_1,_2,_3,name,...) name
#define _rep(i,n) _range(i,0,n)
#define _range(i,a,b) for(int i=int(a);i<int(b);++i)
#define rep(...) _overload(__VA_ARGS__,_range,_rep,)(__VA_ARGS__)

#define _rrep(i,n) _rrange(i,n,0)
#define _rrange(i,a,b) for(int i=int(a)-1;i>=int(b);--i)
#define rrep(...) _overload(__VA_ARGS__,_rrange,_rrep,)(__VA_ARGS__)

#define _all(arg) begin(arg),end(arg)
#define uniq(arg) sort(_all(arg)),(arg).erase(unique(_all(arg)),end(arg))
#define getidx(ary,key) lower_bound(_all(ary),key)-begin(ary)
#define clr(a,b) memset((a),(b),sizeof(a))
#define bit(n) (1LL<<(n))
#define popcount(n) (__builtin_popcountll(n))

using namespace std;

template<class T>bool chmax(T &a, const T &b) { return (a<b)?(a=b,1):0;}
template<class T>bool chmin(T &a, const T &b) { return (b<a)?(a=b,1):0;}

using ll=long long;
using R=long double;
const R EPS=1e-9; // [-1000,1000]->EPS=1e-8 [-10000,10000]->EPS=1e-7
inline int sgn(const R& r){return(r > EPS)-(r < -EPS);}
inline R sq(R x){return sqrt(max<R>(x,0.0));}

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

// Problem Specific Parameter:

using G=vector<vector<int>>;

int Dreyfus_wagner(const G &graph,const auto &term){
	using W=int; W inf=1<<28;
	const int n=int(graph.size()),t=int(term.size());
	if(t<=1) return 0;
	auto dist=graph;
	vector<vector<W>> opt(1<<t,vector<W>(n,inf));

	rep(k,n)rep(i,n)rep(j,n) chmin(dist[i][j],dist[i][k]+dist[k][j]);
	
	map<int,int> dict;
	rep(i,t){
		dict[term[i]]=1<<i;
		rep(j,n) opt[1<<i][j]=dist[term[i]][j];
		rep(j,t) opt[(1<<i)|(1<<j)][term[j]]=dist[term[i]][term[j]];
	}

	auto next_combination=[&](int s){
		int x=s&-s,y=s+x;
		return ((s&~y)/x>>1)|y;
    };

	rep(k,2,t){
		for(int s=(1<<k)-1;s<(1<<t);s=next_combination(s)){
			rep(i,n){
				int ns=s|dict[i];
				if(dict[i] and s==ns) continue;
				for(int u=(s-1)&s;u!=0;u=(u-1)&s){
					int c=s&(~u);
					chmin(opt[ns][i],opt[u][i]+opt[c][i]);
				}
			}
		}
		for(int s=(1<<k)-1;s<(1<<t);s=next_combination(s)){
			rep(i,n){
				int ns=s|dict[i];
				if(dict[i] and s==ns) continue;
				rep(j,n) chmin(opt[ns][i],opt[s][j]+dist[j][i]);
			}
		}
	}

	const int mask=(1<<t)-1;
	W ans=opt[mask][0];
	rep(i,n) chmin(ans,opt[mask][i]);
	return ans;
}

int main(void){
	int h,w;
	while(cin >> h >> w){
		if(h==0) break;
		const int inf=1<<28;

		G graph(h*w,vector<int>(h*w,inf));
		rep(i,h*w) graph[i][i]=0;
		vector<int> term;

		rep(i,h*w){
			int in;
			cin >> in;
			if(in) term.push_back(i);
		}
		
		rep(i,h)rep(j,w){
			const int cur=w*i+j;
			if(i+1<h) graph[cur][cur+w]=graph[cur+w][cur]=1;
			if(j+1<w) graph[cur][cur+1]=graph[cur+1][cur]=1;
		}
		int res=Dreyfus_wagner(graph,term);
		cout << h*w-1-res << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3260
final_rank: 12

code_snippet: #include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef int Weight;
typedef vector<Weight> Array;
typedef vector<Array> Matrix;
const int MAX_T = 6;
const int MAX_N = 12 * 12;
const int INF = 1 << 25;

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

	Matrix d(g); // all-pair shortest
	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 << MAX_T)][MAX_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) // 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 = 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 H, W;

int toV(int x, int y) {
	return y * W + x;
};

int main() {
	cin.tie(0);
	ios::sync_with_stdio(false);

	while (cin >> H >> W , H) {
		vector<int> T;
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				int b;
				cin >> b;
				if (b == 1) T.push_back(toV(j, i));
			}
		}

		Matrix g(H * W, Array(H * W, INF));
		for (int i = 0; i < H * W; i++) {
			g[i][i] = 0;
		}
		for (int i = 0; i < H; i++) {
			for (int j = 0; j < W; j++) {
				if (i != H - 1) {
					g[toV(j, i)][toV(j, i + 1)] = g[toV(j, i + 1)][toV(j, i)] = 1;
				}
				if (j != W - 1) {
					g[toV(j, i)][toV(j + 1, i)] = g[toV(j + 1, i)][toV(j, i)] = 1;
				}
			}
		}

		int res = minimum_steiner_tree(T, g);
		cout << H * W - res - 1 << endl;
	}
}
accuracy: 1
time_ms: 50
memory_kb: 1428
final_rank: 2

code_snippet: #include<bits/stdc++.h>
using namespace std;

typedef int weight;
typedef vector<int> vec;
typedef vector<vec> matrix;
const int inf = (1<<29);
weight OPT[(1<<7)][200];
weight minimum_steiner_tree(const vector<int>& T, const matrix &g) {
  memset( OPT,0,sizeof( OPT ) );
  const int n = g.size();
  const int numT = T.size();
  if (numT <= 1) return 0;

  matrix d(g); // all-pair shortest

  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] );
  
  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) // 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 = 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(){
  int H,W;
  while( cin >> H >> W && (H||W) ){
    vector<int> T;
    matrix G;
    G.resize( H*W, vec( H*W, inf ) );
    int dx[]={1,0,-1,0};
    int dy[]={0,1,0,-1};
    for(int i=0;i<H;i++){
      for(int j=0;j<W;j++){
        G[ i*W + j ][ i*W + j] = 0;
        int c; cin >> c;
        if( c == 1 ) T.push_back( i*W+j );
        for(int k=0;k<4;k++){
          int nx = j + dx[k] , ny = i + dy[k];
          if( nx < 0 || ny < 0 || nx >= W || ny >= H ) continue;
          G[ i*W + j ][ ny*W + nx ] = 1;
        }
      }
    }
    cout << H*W - 1 - minimum_steiner_tree( T, G ) << endl;
  }
}
accuracy: 1
time_ms: 30
memory_kb: 3292
final_rank: 15

code_snippet: #include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <complex>
#include <queue>
#include <deque>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <iomanip>
#include <assert.h>
#include <array>
#include <cstdio>
#include <cstring>
#include <random>
#include <functional>
#include <numeric>
#include <bitset>
#include <fstream>

using namespace std;

#define REP(i,a,b) for(int i=a;i<(int)b;i++)
#define rep(i,n) REP(i,0,n)
#define all(c) (c).begin(), (c).end()
#define zero(a) memset(a, 0, sizeof a)
#define minus(a) memset(a, -1, sizeof a)
#define watch(a) { cout << #a << " = " << a << endl; }
template<class T1, class T2> inline bool minimize(T1 &a, T2 b) { return b < a && (a = b, 1); }
template<class T1, class T2> inline bool maximize(T1 &a, T2 b) { return a < b && (a = b, 1); }

typedef long long ll;
int const inf = 1<<29;

typedef vector<int> vec;
typedef vector<vec> matrix;

typedef int weight;

weight OPT[1 << 7][12*12+10];

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

  matrix d(g); // all-pair shortest
  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] );

  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) // 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 = 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 dx[4] = {-1,0,1,0};
int dy[4] = {0,-1,0,1};

template<class T> constexpr bool in_range(T y, T x, T H, T W) { return 0<=y&&y<H&&0<=x&&x<W; }

int main() {

  for(int H, W; cin >> H >> W && (H|W);) {
    zero(OPT);
    matrix mat(H, vec(W));
    rep(i, H) rep(j, W)
      cin >> mat[i][j];

    vector<int> T;
    rep(i, H) rep(j, W)
      if(mat[i][j])
        T.push_back(i * W + j);

    matrix mat2(H*W, vec(H*W, inf));

    rep(i, H) {
      rep(j, W) {
        mat2[i*W+j][i*W+j] = 0;
        rep(k, 4) {
          const int ni = i + dy[k], nj = j + dx[k];
          if(in_range(ni, nj, H, W)) {
            mat2[i*W+j][ni*W+nj] /*= mat2[ni*W+nj][i*W+j]*/ = 1;
          }
        }
      }
    }

//    rep(i, H*W) rep(j, W)     printf("%10d%c", mat2[i][j], j < W-1 ? ' ' : '\n');

    int ms = minimum_steiner_tree(T, mat2);
    cout << H * W - (1 + ms) << endl;

  }
  
  return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3204
final_rank: 9

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define INF (1<<29)
typedef vector<int> Vec;
typedef vector<Vec> Graph;

int minimum_steiner_tree(Graph &d, Vec &heart)
{
    int N = d.size(), T = heart.size();
    if (T <= 1) return T;   
    
    int dp[1<<T][N];
    for (int i = 0; i < (1<<T); i++) {
        for (int j = 0; j < N; j++) {
            dp[i][j] = INF;
        }
    }

    for (int i = 0; i < T; i++) {
        for (int j = 0; j < N; j++) {
            dp[1<<i][j] = d[heart[i]][j];
        }
    }

    for (int i = 1; i < (1<<T); i++) {
        if (!(i & (i - 1))) continue;
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < i; k++) {
                if ((i | k) == i) {
                    dp[i][j] = min(dp[i][j], dp[k][j] + dp[i-k][j]);
                }
            }
        }
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++) {
                dp[i][j] = min(dp[i][j], dp[i][k] + d[j][k]);
            }
        }
    }
    int res = INF;
    for (int i = 0; i < (1<<T); i++) {
        for (int j = 0; j < N; j++) {
            res = min(res, dp[i][j] + dp[((1<<T)-1)-i][j]);
        }
    }
    return res + 1;
}

int get_dist(int y1, int x1, int y2, int x2)
{
    return abs(x1 - x2) + abs(y1 - y2);
}

int main()
{
    int H, W, x;
    while (cin >> H >> W, H) {
        Vec heart;
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                cin >> x;  
                if (x == 1) {
                    heart.push_back(i * W + j);
                }
            }
        }

        Graph G(H*W, Vec(H*W));
        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] = get_dist(i, j, k, l);
                    }
                }
            }
        }
        cout << H*W - minimum_steiner_tree(G, heart) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3164
final_rank: 6

code_snippet: #include <bits/stdc++.h>

using namespace std;

#define INF (1<<29)
typedef vector<int> Vec;
typedef vector<Vec> Graph;

int minimum_steiner_tree(Graph &d, Vec &heart)
{
    int N = d.size(), T = heart.size();
    if (T <= 1) return T;
    
    int dp[1<<T][N];
    for (int i = 0; i < (1<<T); i++) {
        for (int j = 0; j < N; j++) {
            dp[i][j] = INF;
        }
    }

    for (int i = 0; i < T; i++) {
        for (int j = 0; j < N; j++) {
            dp[1<<i][j] = d[heart[i]][j];
        }
    }

    for (int i = 1; i < (1<<T); i++) {
        if (!(i & (i - 1))) continue;
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < i; k++) {
                if ((i | k) == i) {
                    dp[i][j] = min(dp[i][j], dp[k][j] + dp[i-k][j]);
                }
            }
        }
        for (int j = 0; j < N; j++) {
            for (int k = 0; k < N; k++) {
                dp[i][j] = min(dp[i][j], dp[i][k] + d[j][k]);
            }
        }
    }
    int res = INF;
    for (int i = 0; i < (1<<T); i++) {
        for (int j = 0; j < N; j++) {
            res = min(res, dp[i][j] + dp[((1<<T)-1)-i][j]);
        }
    }
    return res + 1;
}

int get_dist(int y1, int x1, int y2, int x2)
{
    return abs(x1 - x2) + abs(y1 - y2);
}

int main()
{
    int H, W, x;
    while (cin >> H >> W, H) {
        Vec heart;
        for (int i = 0; i < H; i++) {
            for (int j = 0; j < W; j++) {
                cin >> x;  
                if (x == 1) {
                    heart.push_back(i * W + j);
                }
            }
        }

        Graph G(H*W, Vec(H*W));
        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] = get_dist(i, j, k, l);
                    }
                }
            }
        }
        cout << H*W - minimum_steiner_tree(G, heart) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 1340
final_rank: 1

code_snippet: #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);
	}
}
accuracy: 1
time_ms: 60
memory_kb: 1356
final_rank: 3

code_snippet: #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
accuracy: 1
time_ms: 180
memory_kb: 2448
final_rank: 20

code_snippet: #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;
}
accuracy: 1
time_ms: 60
memory_kb: 1416
final_rank: 4

code_snippet: #include <cassert>// c
#include <iostream>// io
#include <iomanip>
#include <fstream>
#include <sstream>
#include <vector>// container
#include <map>
#include <set>
#include <queue>
#include <bitset>
#include <stack>
#include <algorithm>// other
#include <complex>
#include <numeric>
#include <functional>
#include <random>
#include <regex>
using namespace std;

typedef long long  ll;

#define ALL(c) (begin(c)),(end(c))
#define REP(i,n) FOR(i,0,n)
#define REPr(i,n) FORr(i,0,n)
#define FOR(i,l,r) for(int i=(int)(l);i<(int)(r);++i)
#define FORr(i,l,r) for(int i=(int)(r)-1;i>=(int)(l);--i)
#define EACH(it,o) for(auto it = (o).begin(); it != (o).end(); ++it)
#define IN(l,v,r) ((l)<=(v) && (v)<(r))
#define UNIQUE(v) v.erase(unique(ALL(v)),v.end())
//debug
#define DUMP(x)  cerr << #x << " = " << (x)
#define LINE()    cerr<< " (L" << __LINE__ << ")"

class range {
private:
	struct Iter{
		int v;
		int operator*(){return v;}
		bool operator!=(Iter& itr) {return v < itr.v;}
		void operator++() {++v;}
	};
	Iter i, n;
public:
	range(int n) : i({0}), n({n}) {}
	range(int i, int n) : i({i}), n({n}) {}
	Iter& begin() {return i;}
	Iter& end() {return n;}
};

//output
template<typename T> ostream& operator << (ostream& os, const vector<T>& as){REP(i,as.size()){if(i!=0)os<<" "; os<<as[i];}return os;}
template<typename T> ostream& operator << (ostream& os, const vector<vector<T>>& as){REP(i,as.size()){if(i!=0)os<<endl; os<<as[i];}return os;}
template<typename T> ostream& operator << (ostream& os, const set<T>& ss){for(auto a:ss){if(a!=ss.begin())os<<" "; os<<a;}return os;}
template<typename T1,typename T2> ostream& operator << (ostream& os, const pair<T1,T2>& p){os<<p.first<<" "<<p.second;return os;}
template<typename K,typename V> ostream& operator << (ostream& os, const map<K,V>& m){bool isF=true;for(auto& p:m){if(!isF)os<<endl;os<<p;isF=false;}return os;}
template<typename T1> ostream& operator << (ostream& os, const tuple<T1>& t){os << get<0>(t);return os;}
template<typename T1,typename T2> ostream& operator << (ostream& os, const tuple<T1,T2>& t){os << get<0>(t)<<" "<<get<1>(t);return os;}
template<typename T1,typename T2,typename T3> ostream& operator << (ostream& os, const tuple<T1,T2,T3>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5,typename T6> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5,T6>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t)<<" "<<get<5>(t);return os;}
template<typename T1,typename T2,typename T3,typename T4,typename T5,typename T6,typename T7> ostream& operator << (ostream& os, const tuple<T1,T2,T3,T4,T5,T6,T7>& t){os << get<0>(t)<<" "<<get<1>(t)<<" "<<get<2>(t)<<" "<<get<3>(t)<<" "<<get<4>(t)<<" "<<get<5>(t)<<" "<<get<6>(t);return os;}

//input
char tmp[1000];
#define nextInt(n) scanf("%d",&n)
#define nextLong(n) scanf("%lld",&n) //I64d
#define nextDouble(n) scanf("%lf",&n) 
#define nextChar(n) scanf("%c",&n)
#define nextString(n) scanf("%s",tmp);n=tmp

// values
template<typename T> T INF(){assert(false);};
template<> int INF<int>(){return 1<<28;};
template<> ll INF<ll>(){return 1LL<<58;};
template<> double INF<double>(){return 1e16;};

template<class T> T EPS(){assert(false);};
template<> int EPS<int>(){return 1;};
template<> ll EPS<ll>(){return 1LL;};
template<> double EPS<double>(){return 1e-8;};
template<> long double EPS<long double>(){return 1e-8;};

template<typename T,typename U> T pfmod(T v,U M){return fmod(fmod(v,M)+M,M);}

ll gcd_positive(ll a,ll b) { return b == 0 ? a : gcd_positive(b,a%b); }
ll gcd(ll a,ll b) { return gcd_positive(abs(a), abs(b)); }
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}

namespace EGraph{
	typedef ll Cost;Cost CINF=INF<Cost>();
	struct Edge{
		int from,to;Cost cost;
		Edge(int from,int to,Cost cost)
		: from(from),to(to),cost(cost) {};
		bool operator<(Edge r) const{ return cost<r.cost;}
		bool operator>(Edge r) const{ return cost>r.cost;}
	};
	typedef vector<vector<Edge> >  Graph;
}
using namespace EGraph;


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


// |S| <= 31
class subset{
	private:
	struct Iter{
		int v,bit;
		int operator*(){
			int res=0,vi=0;
			REP(bi,32)if(bit & (1<<bi)){
				if(v&(1<<vi))res+=1<<bi;
				vi++;
			}
			return res;
		}
		bool operator!=(Iter& itr) {return v < itr.v;}
		void operator++(){++v;}
	};
	Iter i, n;
	public:
	subset(int bit){
		i={0,bit};n={1<<(__builtin_popcount(bit)),bit};
	}
	Iter& begin() {return i;}
	Iter& end() {return n;}
};
 
class Main{
	typedef ll Cost;

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

		// all-pair shortest
		vector<vector<Cost>> ds=g;REP(k,n)REP(i,n)REP(j,n) ds[i][j] = min(ds[i][j], ds[i][k] + ds[k][j]);

		vector<vector<Cost>> dp(1<<ts.size(),vector<ll>(n,INF<Cost>()));
		REP(i,ts.size())REP(q,n) dp[1 << i][q] = ds[ts[i]][q];
		
		REP(S,1<<ts.size()){
			REP(p,n)for(int E :subset(S)) dp[S][p]=min(dp[S][p],dp[E][p] + dp[S-E][p]);
			REP(p,n)REP(q,n) dp[S][p] = min(dp[S][p], dp[S][q] + ds[p][q] );
		}
		Cost res =INF<Cost>();REP(q,n)res = min(res,dp[((1 << ts.size())-1)][q]);
		return res;
	}

	public:
	void run(){
		while(true){
			int H,W;cin >> H >>W;if(H==0 && W==0)break;
			vector<vector<int>> board(H,vector<int>(W));
			REP(y,H)REP(x,W)cin >> board[y][x];

			vector<vector<ll>> mat(H*W,vector<ll>(H*W,INF<ll>()));
			REP(i,H*W)mat[i][i]=0;

			vector<int> vs;
			REP(y,H)REP(x,W)if(board[y][x])vs.push_back(y*W+x);
			
			REP(y,H)REP(x,W){
				REP(d,4){
					int ny=y+dy[d],nx=x+dx[d];
					if(!IN(0,nx,W) || !IN(0,ny,H))continue;
					mat[y*W+x][ny*W+nx]=1;
				}
			}
			cout << H*W - (1+minimum_steiner_tree(vs,mat)) <<endl;

		}
	}
};

int main(){
	cout <<fixed<<setprecision(20);
	cin.tie(0);
	ios::sync_with_stdio(false);
	Main().run();
	return 0;
}
accuracy: 1
time_ms: 100
memory_kb: 1636
final_rank: 5