#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <iostream>
#include <vector>
#include <string>
#include <list>
#include <set>
#include <map>
#include <stack>
#include <queue>
using namespace std;

#define int64 long long
#define uint64 unsigned long long
#define pb push_back
#define mp make_pair


struct point {
	int x, y;
	point(int x, int y) {
		this->x = x;
		this->y = y;
	}
};

int main() {
	int m, n, i, j;
	cin >> m >> n;
	string str;
	getline(cin, str);
	vector< vector<bool> > mask(m), used(m);
	for (i = 0; i < m; ++i) {
		mask[i].resize(n);
		used[i].resize(n);
		getline(cin, str);
		for (j = 0; j < n; ++j) {
			used[i][j] = false;
			mask[i][j] = (str[j] == '1');
		}
	}

	int c = 0, s = 0;
	for (i = 0; i < m; ++i) {
		for (j = 0; j < n; ++j) {
			if (!used[i][j]) {
				if (mask[i][j]) {
					++c;
					int cur = 0;
					queue<point> q;
					q.push(point(j, i));
					while (!q.empty()) {
						point p = q.front();
						q.pop();
						used[p.y][p.x] = true;
						++cur;
						if (p.x > 0 && !used[p.y][p.x - 1] && mask[p.y][p.x - 1]) q.push(point(p.x - 1, p.y));
						if (p.x < n - 1 && !used[p.y][p.x + 1] && mask[p.y][p.x + 1]) q.push(point(p.x + 1, p.y));
						if (p.y > 0 && !used[p.y - 1][p.x] && mask[p.y - 1][p.x]) q.push(point(p.x, p.y - 1));
						if (p.y < m - 1 && !used[p.y + 1][p.x] && mask[p.y + 1][p.x]) q.push(point(p.x, p.y + 1));
					}

					if (s < cur) s = cur;
				}
			}
		}
	}

	cout << c << ' ' << s << endl;
	return 0;
}