#include <bits/stdc++.h>

#define FOR0(i,n) for (int i = 0; i < n; i++)
#define FOR(i,j, n) for (int i = j; i < n; i++)
// bool isEven(ll n) {return (n%2!=0)?false:true;};
#define INF 1000000000 // 1 billion, safer than 2B for Floyd Warshall’s

#define f(i,a,b) for(i=a;i<b;i++)
#define rep(i,n) f(i,0,n)
#define fd(i,a,b) for(i=a;i>=b;i--)
#define pb push_back
#define mp make_pair
#define vi vector< int >
#define vl vector< ll >
#define ss second
#define ff first
#define ll long long
#define pii pair< int,int >
#define pll pair< ll,ll >
#define sz(a) a.size()
#define inf (1000*1000*1000+5)
#define all(a) a.begin(),a.end()
#define tri pair<int,pii>
#define vii vector<pii>
#define vll vector<pll>
#define viii vector<tri>
#define mod (1000*1000*1000+7)
#define pqueue priority_queue< int >
#define pdqueue priority_queue< int,vi ,greater< int > >
// #define int ll

using namespace std;

//atcoder
// Dwango Programming Contest 6th
//d

///////////////////////////////////////////////////////////////////////////////////
// int minSteps(const vector<vector<char> > &maze, vector<vector<bool> > &visited,
//              int i, int j, int r, int s, int row, int col)
// {
//     int level = 1;

//     queue<pair<int, int> > q;
//     q.push(make_pair(i, j));
//     visited[i][j] = true;

//     pair<int, int> curr;

//     while(!q.empty())
//     {
//         int n = q.size();

//         for (int k = 0; k < n; ++k)
//         {
//             curr = q.front();
//             q.pop();


//             if(curr.first==r&&curr.second==s)
//                 return level;

//             // (i-1, j)
//             if(i-1>=0 && maze[i-1][j]!='#' && !visited[i-1][j])
//             {
//                 visited[i-1][j] = true;
//                 q.push(make_pair(i-1, j));
//             }

//             // (i+1, j)
//             if(i+1<row && maze[i+1][j]!='#' && !visited[i+1][j])
//             {
//                 visited[i+1][j] = true;
//                 q.push(make_pair(i+1, j));
//             }

//             // (i, j-1)
//             if(j-1>=0 && maze[i][j-1]!='#' && !visited[i][j-1])
//             {
//                 visited[i][j-1] = true;
//                 q.push(make_pair(i, j-1));
//             }

//             // (i, j+1)
//             if(j+1<col && maze[i][j+1]!='#' && !visited[i][j+1])
//             {
//                 visited[i][j+1] = true;
//                 q.push(make_pair(i, j+1));
//             }
//         }
//         level++;
//     }
//     return -1;
// }
///////////////////////////////////////////////////////////////////////////////////


void fillVisited(vector<vector<bool> > &visited, int row, int col)
{
    for (int i = 0; i < row; i++)
        for(int j = 0; j < col; j++)
            visited[i][j] = false;
}

int BFS(const vector<vector<char> > &maze, vector<vector<bool> > &visited, 
         vector<vector<int> > &result, int i, int j, int row, int col)
{
    queue<pair<int, int> > q;

    q.push(make_pair(i, j));
    visited[i][j] = true;

    pair<int, int> curr;

    int level = -1;

    while(!q.empty())
    {
        int n = q.size();

        for (int k = 0; k < n; ++k)
        {
            curr = q.front();
            q.pop();

            int c_i = curr.first;
            int c_j = curr.second;

            // cout<<c_i<<" "<<c_j<<endl;

            // CAN GO IN 4 directions
            if(c_j+1<col && !visited[c_i][c_j+1] && maze[c_i][c_j+1]!='#')
            {   
                q.push(make_pair(c_i, c_j+1));
                visited[c_i][c_j+1] = true;
            }
            
            if(c_i+1<row && !visited[c_i+1][c_j] && maze[c_i+1][c_j]!='#')
            {
                q.push(make_pair(c_i+1, c_j));
                visited[c_i+1][c_j] = true;
            }

            if(c_i-1>=0 && !visited[c_i-1][c_j] && maze[c_i-1][c_j]!='#')
            {
                q.push(make_pair(c_i-1, c_j));
                visited[c_i-1][c_j] = true;
            }

            if(c_j-1>=0 && !visited[c_i][c_j-1] && maze[c_i][c_j-1]!= '#')
            {
                q.push(make_pair(c_i, c_j-1));
                visited[c_i][c_j-1] = true;
            }
        }
        level++;
    }

    return level;
}

int main()
{
    int row, col;
    cin>>row>>col;

    vector<vector<char> > maze(row);

    for (int i = 0; i < row; ++i)
    {
        char temp;
        for (int j = 0; j < col; ++j)
        {
            cin>>temp;
            maze[i].push_back(temp);
        }
    }


    vector<vector<int> > result(row, vector<int> (col, INT_MAX));

    vector<vector<bool> > visited(row, vector<bool> (col, false));

    int res = -1;


    for (int i = 0; i < row; ++i)
    {
        for (int j = 0; j < col; ++j)
        {
            fillVisited(visited, row, col);
            if(maze[i][j]!='#')
            {
                res = max(res, BFS(maze, visited, result, i, j, row, col));
                // cout<<BFS(maze, visited, result, i, j, row, col)<<endl;
            }
            // cout<<endl;
        }
    }

    cout<<res<<endl;
}

Measured memory_bytes: 256