#include <bits/stdc++.h>
#pragma GCC optimize("Ofast,inline,unroll-loops,fast-math")
using namespace std;
int main(int argc, char *argv[]) {
  int h, w;
  cin >> h >> w;
  vector<string> vs;
  for (int i = 0; i < h; i++) {
    string s;
    cin >> s;
    vs.push_back(s);
  }
  int c = 0;
  vector<pair<int, int>> v1, v2;
  for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
      if (vs[i][j] == '.') c++;
      if (vs[i][j] == '.' && v1.size() == 0) {
        v1.push_back(make_pair(i, j));
      }
    }
  }
  int cc = 1;
  vector<pair<int, int>> dir = {make_pair(-1, 0), make_pair(1, 0),
                                make_pair(0, 1), make_pair(0, -1)};
  unordered_map<int, unordered_map<int, int>> um;
  um[v1[0].first][v1[0].second] = 1;
  while (cc < c) {
    v2.clear();
    for (auto node : v1) {
      for (auto p : dir) {
        int x = node.first + p.first, y = node.second + p.second;
        if (x < 0 || y < 0 || x >= h || y >= w) continue;
        if (vs[x][y] == '#' || um[x][y] == 1) continue;
        cc++;
        v2.push_back(make_pair(x, y));
        um[x][y] = 1;
      }
    }
    v1 = v2;
  }
  int res = 0;
  auto vv = v1;
  for (auto vvv : vv) {
    um.clear();
    v1.clear();
    v1.push_back(vvv);
    int r = 0;
    while (v1.size() > 0) {
      v2.clear();
      for (auto node : v1) {
        for (auto p : dir) {
          int x = node.first + p.first, y = node.second + p.second;
          if (x < 0 || y < 0 || x >= h || y >= w) continue;
          if (vs[x][y] == '#' || um[x][y] == 1) continue;
          v2.push_back(make_pair(x, y));
          um[x][y] = 1;
        }
      }
      v1 = v2;
      r++;
    }
    res = max(res, r - 1);
  }
  cout << res << endl;
}
