#include #include #include #include using namespace std; struct disjoint_set { vector p, sz; disjoint_set(int n) { p.assign(n, -1); sz.resize(n); } int find(int x) { return p[x] < 0 ? x : (p[x] = find(p[x])); } int getsz(int x) { return sz[find(x)]; } bool merge(int x, int y) { x = find(x); y = find(y); if(x == y) return false; p[x] = y; sz[y] += sz[x]; return true; } }; int main() { int r, c; cin >> r >> c; { string s; getline(cin, s); } vector g(r); for(auto& x: g) getline(cin, x); disjoint_set dsu(r*c); for(int i = 0; i < r; i++) { for(int j = 0; j < c; j++) { if(g[i][j] == 'X') continue; if(g[i][j] == '.') dsu.sz[i*c+j] = 1; bool entrance = (g[i][j] >= 'A' && g[i][j] <= 'W'); if(i && g[i-1][j] != 'X' && (!entrance || g[i-1][j] < 'A' || g[i-1][j] > 'W')) dsu.merge(i*c+j, i*c+j-c); if(j && g[i][j-1] != 'X' && (!entrance || g[i][j-1] < 'A' || g[i][j-1] > 'W')) dsu.merge(i*c+j, i*c+j-1); } } int numentrances = 0; vector can(r*c); for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) { if(i == 0 || i == r-1 || j == 0 || j == c-1) { int id = dsu.find(i*c+j); if(can[id]) continue; if(dsu.getsz(id) == 0) continue; numentrances++; can[id] = true; } } int bad = 0; for(int i = 0; i < r; i++) for(int j = 0; j < c; j++) { if(!can[dsu.find(i*c+j)] && dsu.getsz(i*c+j)) { bad += dsu.getsz(i*c+j); can[dsu.find(i*c+j)] = true; } } cout << numentrances << " " << bad << "\n"; }