#include <iostream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <cmath>
#include <string>

using std::cin;
using std::cout;
using std::endl;
using std::min;
using std::max;
using std::vector;
using std::string;

using llint = long long int;

int main()
{

	
	int H,W;
	
	cin >> H >> W;

	
	vector<int> S(H * W);
	vector<int> E(H * W * H * W);

	auto over = [&](int i,int j)->bool{
		return i < 0 || H <= i || j < 0 || W <= j;
	};

	auto gs = [&](int i,int j)->auto&{
		return S[i*W + j];
	};
	auto ge = [&](int i,int j, int m,int n)->auto&{
		return E[i* W * W * H + j * W * H + m * W + n];
	};
	for (auto& a:E)a = 1000;

	for (size_t i =0 ; i < H;i++){
		for (size_t j =0 ; j < W;j++){
			char c;
			cin >> c;
			if(c == '.')gs(i,j) = 1;
			else gs(i,j) = 0;
		}
	}

	for (size_t i =0 ; i < H;i++){
		for (size_t j =0 ; j < W;j++){
			if(gs(i,j)){
				ge(i,j,i,j) = 0;
				if(!over(i+1,j))if(gs(i+1,j)){
					ge(i,j,i+1,j) = 1;
					ge(i+1,j,i,j) = 1;
				}
				if(!over(i,j+1))if(gs(i,j+1)){
					ge(i,j,i,j + 1) = 1;
					ge(i,j + 1,i,j) = 1;
				}
			}
		}
	}

	bool changed = true;

	for (size_t k =0 ; k < 300;k++){

		for (size_t i =0 ; i < H;i++){
			for (size_t j =0 ; j < W;j++){
				for (size_t n = 0; n < H;n++){
					for (size_t m = 0; m < W;m++){
						for (size_t o = 0; o < H;o++){
							for (size_t p = 0; p < W;p++){
								ge(i,j,n,m) = min(ge(i,j,n,m), ge(i,j,o,p) + ge(o,p,n,m));
							}
						}
					}
				}
			}
		}
	}

	int a = 0;
	for (auto d : E){
		if(d < 1000){
			a = max(a,d);
		}
	}

	cout << a << endl;


	return 0;
}
