import java.io.*;
import java.util.*;
class Main{
static BufferedReader read = new BufferedReader(new InputStreamReader(System.in));
static int N = 52, row, col;
static int[][] a = new int[N][N];
static boolean[][] st = new boolean[N][N];
static int[][] dir = new int[][]{{0, -1}, {-1,0}, {0, 1}, {1, 0}};
public static void main(String[] args) throws Exception{
String[] ss = read.readLine().split(" ");
row = Integer.valueOf(ss[0]); col = Integer.valueOf(ss[1]);
for(int i = 0; i < row; i++){
ss = read.readLine().split(" ");
for(int j = 0; j < col; j++){
a[i][j] = Integer.valueOf(ss[j]);
}
}
int cnt = 0, area = 0;
for(int i = 0; i < row; i++){
for(int j = 0; j < col; j++){
if(!st[i][j]){
area = Math.max(area, bfs(i, j));
cnt++;
}
}
}
System.out.println(cnt);
System.out.println(area);
}
public static int bfs(int x, int y){
Queue<Integer> q = new LinkedList();
int ref = reflect(x, y);
q.offer(ref);
st[x][y] = true;
int res = 1;
while(!q.isEmpty()){
int poll = q.poll();
int[] def = deflect(poll);
for(int i = 0; i < 4; i++){
// i方向有墙, 0: 西, 1:北, 2: 东, 3: 南
if((a[def[0]][def[1]] >> i & 1) != 0) continue;
int nx = def[0] + dir[i][0];
int ny = def[1] + dir[i][1];
if(nx < 0 || nx >= row || ny < 0 || ny >= col) continue;
if(st[nx][ny]) continue;
st[nx][ny] = true;
ref = reflect(nx, ny);
res++;
q.offer(ref);
}
}
return res;
}
public static int reflect(int x, int y){
return x * col + y;
}
public static int[] deflect(int a){
return new int[]{a / col, a % col};
}
}