Each searchlight has a maximum level. You can decrease a searchlight’s level to save the energy. A searchlight whose maximum level is k can be turned to level k, k-1, k-2, …, 1 and 0. Level 0 means turning off the searchlight.
A grid is well-guarded if and only if at least one of the following two conditions is satisfied:
1.There is a searchlight in this grid, and it is not switched to level 0 (the light is on).
2.The grid is lightened by at least two searchlights. One lightens it in horizontal direction (east or west), and another lightens it in vertical direction (north or south).
Chandler asks you to help finding a solution that he can turn on some of the searchlights so that:
1.All the grids are well-guarded.
2.All the searchlights turned on are in a same level.
3.That same level mentioned above is as small as possible.
More specifically, if you choose a same level Q, then all the searchlights whose maximum level are less than Q have to be turned off. Please help him to find a solution with the minimum same level.
For each test case, the first line is two integers n and m, representing a grids land of size n×m. (0<n<=100, 0<m<=10000). Following n lines describe an n×m matrix in which ai,j means the maximum level of the searchlight in grid (i, j). ai,j can be zero, which means there is no searchlight on that grid. For all the cases, ai, j<=10000.
The input file ends with a line containing two zeros.
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
typedef long long LL; const int MAXN = ;
const int MAXM = ; struct Node {
int a, x, y;
bool operator < (const Node &rhs) const {
if(a != rhs.a) return a < rhs.a;
if(x != rhs.x) return x < rhs.x;
return y < rhs.y;
}
} p[MAXN * MAXM]; int mat[MAXN][MAXM];
int xfa[MAXM][MAXN], yfa[MAXN][MAXM];
int xsize[MAXM][MAXN], ysize[MAXN][MAXM];
int n, m, s; void init() {
for(int j = ; j <= m; ++j)
for(int i = ; i <= n; ++i) xfa[j][i] = i, xsize[j][i] = ;
for(int i = ; i <= n; ++i)
for(int j = ; j <= m; ++j) yfa[i][j] = j, ysize[i][j] = ;
} int find_set(int *fa, int x) {
return fa[x] == x ? x : fa[x] = find_set(fa, fa[x]);
} void merge(int *fa, int *size, int x, int y) {
int fx = find_set(fa, x), fy = find_set(fa, y);
if(size[fx] < size[fy]) swap(fx, fy);
size[fx] += size[fy];
fa[fy] = fx;
} int solve() {
int largest = ;
for(int k = , i = ; i < s; ++k) {
if(k - >= largest) return k;
while(i < s && p[i].a == k) {
int x = p[i].x, y = p[i].y;
if(x - >= && mat[x - ][y] <= k) merge(xfa[y], xsize[y], x - , x);
if(x + <= n && mat[x + ][y] < k) merge(xfa[y], xsize[y], x, x + );
if(y - >= && mat[x][y - ] <= k) merge(yfa[x], ysize[x], y - , y);
if(y + <= m && mat[x][y + ] < k) merge(yfa[x], ysize[x], y, y + ); int fx = find_set(xfa[y], x), fy = find_set(yfa[x], y);
if(xsize[y][fx] == n || ysize[x][fy] == m) return -; if(find_set(xfa[y], ) == fx || find_set(xfa[y], n) == fx)
largest = max(largest, xsize[y][fx]);
else largest = max(largest, (xsize[y][fx] + ) / );
if(find_set(yfa[x], ) == fy || find_set(yfa[x], m) == fy)
largest = max(largest, ysize[x][fy]);
else largest = max(largest, (ysize[x][fy] + ) / ); ++i;
}
}
return -;
} int main() {
while(scanf("%d%d", &n, &m) != EOF) {
if(n == && m == ) break;
s = ;
for(int i = ; i <= n; ++i) {
for(int j = ; j <= m; ++j) {
scanf("%d", &mat[i][j]);
p[s].x = i;
p[s].y = j;
p[s++].a = mat[i][j];
}
}
sort(p, p + s);
init();
int ans = solve();
if(ans == -) puts("NO ANSWER!");
else printf("%d\n", ans);
}
}