#include <bits/stdc++.h>
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#pragma comment(linker, "/stack:200000000")
using namespace std;
void io() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);
}
int h, w;
char s[25][25];
int a[25][25];
bool vis[25][25];
int d[4][2] = {1, 0, 0, 1, -1, 0, 0, -1};
struct UnionSet {
  int pa[25 * 110];
  void init(int n) {
    for (int i = 1; i <= n; i++) pa[i] = i;
  }
  int find(int x) { return pa[x] == x ? x : pa[x] = find(pa[x]); }
  bool IsSame(int x, int y) { return find(x) == find(y); }
  int union_vertices(int x, int y) {
    int xr = find(x), yr = find(y);
    if (xr != yr) {
      pa[yr] = xr;
      return 1;
    }
    return 0;
  }
} U;
void bfs(pair<int, int> p) {
  memset(vis, false, sizeof(vis));
  queue<pair<int, int> > q;
  q.push(p);
  vis[p.first][p.second] = true;
  while (!q.empty()) {
    pair<int, int> tp = q.front();
    int dep = a[tp.first][tp.second] + 1;
    q.pop();
    for (int i = 0; i <= 3; ++i) {
      if (tp.first + d[i][0] < 1 || tp.first + d[i][0] > h ||
          tp.second + d[i][1] < 1 || tp.second + d[i][1] > w)
        continue;
      if (vis[tp.first + d[i][0]][tp.second + d[i][1]]) continue;
      if (a[tp.first + d[i][0]][tp.second + d[i][1]] == -1) continue;
      U.union_vertices(100 * tp.first + tp.second,
                       100 * (tp.first + d[i][0]) + tp.second + d[i][1]);
      a[tp.first + d[i][0]][tp.second + d[i][1]] = dep;
      vis[tp.first + d[i][0]][tp.second + d[i][1]] = true;
      q.push(make_pair(tp.first + d[i][0], tp.second + d[i][1]));
    }
  }
}
int main() {
  io();
  cin >> h >> w;
  for (int i = 1; i <= h; ++i) cin >> (s[i] + 1);
  for (int i = 1; i <= h; ++i) {
    for (int j = 1; j <= w; ++j) {
      U.pa[100 * i + j] = 100 * i + j;
      if (s[i][j] == '#') {
        a[i][j] = -1;
      }
    }
  }
  for (int i = 1; i <= h; ++i) {
    for (int j = 1; j <= w; ++j) {
      if (a[i][j] == -1 || vis[i][j]) continue;
      bfs(make_pair(i, j));
    }
  }
  map<int, pair<int, int> > MP;
  vector<pair<int, int> > st;
  for (int i = 1; i <= h; ++i) {
    for (int j = 1; j <= w; ++j) {
      if (a[i][j] == -1) continue;
      if (a[i][j] > MP[U.find(100 * i + j)].first) {
        MP[U.find(100 * i + j)] = make_pair(a[i][j], 100 * i + j);
      }
      a[i][j] = 0;
    }
  }
  for (auto i : MP)
    st.emplace_back(make_pair(i.second.second / 100, i.second.second % 100));
  for (auto i : st) bfs(i);
  int maxd = 0;
  for (int i = 1; i <= h; ++i) {
    for (int j = 1; j <= w; ++j) {
      maxd = max(maxd, a[i][j]);
    }
  }
  cout << maxd;
}
