#include"bits/stdc++.h"
using namespace std;
using ll=long long;
template<typename T=ll>inline T in(istream&is=cin){T ret;is>>ret;return ret;}
template<typename T>inline auto vec2(typename vector<T>::size_type h,typename vector<T>::size_type w,T v=T()){return vector<vector<T>>(h,vector<T>(w,v));}

int main()
{
    ll h=in(),w=in();
    vector<string>maze(h);
    ll road_cnt=0;
    for(ll i=0;i<h;++i){
        cin>>maze[i];
        road_cnt+=count(maze[i].begin(),maze[i].end(),'.');
    }
    road_cnt=(road_cnt+1)/2;

    ll ans=0;
    auto dist=vec2<ll>(h,w);
    auto visited=vec2<bool>(h,w,false);
    for(ll i=0;i<h;++i){
        for(ll j=0;j<w;++j){
            if(maze[i][j]=='.'){
                queue<pair<ll,ll>>que;
                dist[i][j]=0;
                que.emplace(i,j);
                while(!que.empty()){
                    ll x=que.front().second,y=que.front().first;que.pop();
                    visited[y][x]=true;
                    ll dx[]={0,-1,0,1},dy[]={-1,0,1,0};
                    for(ll k=0;k<4;++k){
                        ll xx=x+dx[k],yy=y+dy[k];
                        if(0<=xx&&xx<w&&0<=yy&&yy<h&&maze[yy][xx]=='.'&&!visited[yy][xx]){
                            ans=max(ans,dist[yy][xx]=dist[y][x]+1);
                            que.emplace(yy,xx);
                        }
                    }
                }
                if(--road_cnt==0){
                    cout<<ans<<endl;
                    return 0;
                }
                for(ll k=0;k<h;++k){
                    for(ll l=0;l<w;++l){
                        dist[k][l]=0;
                        visited[k][l]=false;
                    }
                }
            }
        }
    }
}
