using System;

namespace Kyopuro
{
    class Program
    {
        static void Main(string[] args)
        {

            string[] str = Console.ReadLine().Split(' ');
            int H = int.Parse(str[0]);
            int W = int.Parse(str[1]);

            string[] map = new string[H];

            bool[][] isRoad = new bool[H + 2][];//あるマスは道か
            int[][] count = new int[H+2][];   //あるマスはスタートから何マス必要か
            int countMax=0;//最大必要なマス
            int finalMax=0;//最終的な最大マス
            int x, y;//初期マス
            int loop;//迷路を解く現在の手数
            bool isSomewhereExist=false;//残ったマスがあるかどうか

            int i,j;

            for (i = 0; i < H; i++)
            {
                map[i] = Console.ReadLine();
            }




            //初期化
            for (i = 0; i < H + 2; i++)
            {
                isRoad[i] = new bool[W + 2];
                count[i] = new int[W + 2];
                for (j = 0; j < W + 2; j++)
                {
                    isRoad[i][j] = false;
                    count[i][j] = -1;
                }
            }



            for (i = 1; i < H+1; i++)
            {
                //道の場所を特定する
                for (j = 0; j < W; j++)
                {
                    if(map[i-1].Substring(j,1) == ".")
                    {
                        isRoad[i][j+1] = true;
                    }
                }

                //isRoad[y][x]は，座標x,yに壁があるかないかを示している。
            }


            for (y = 1; y < H+1; y++)
            {
                for (x = 1; x < W+1; x++)//初期座標決定ループ
                {
                    if (!isRoad[y][x])
                    {
                        continue;//スタートが道でないなら次のループへ
                    }

                    //マスの状態を-1に
                    for (i = 0; i < H+2; i++)
                    {
                        for (j = 0; j < W+2; j++)
                        {
                            count[i][j] = -1;
                        }
                    }
                    count[y][x] = 0;//初期マスは0
                    for (loop = 0; loop < 300; loop++)//ループ回数
                    {

                            for (i = 1; i < H + 1; i++)
                            {
                                for (j = 1; j < W + 1; j++)
                                {
                                if (count[i][j] == loop)
                                {
                                    //隣接マスが道かつ今まで通ったことがないなら

                                    if (isRoad[i][j + 1] && count[i][j + 1] == -1)
                                    {
                                        count[i][j + 1] = loop + 1;
                                        countMax = loop + 1;
                                    }

                                    if (isRoad[i][j - 1] && count[i][j - 1] == -1)
                                    {
                                        count[i][j - 1] = loop + 1;
                                        countMax = loop + 1;

                                    }

                                    if (isRoad[i + 1][j] && count[i + 1][j] == -1)
                                    {
                                        count[i + 1][j] = loop + 1;
                                        countMax = loop + 1;

                                    }

                                    if (isRoad[i - 1][j] && count[i - 1][j] == -1)
                                    {
                                        count[i - 1][j] = loop + 1;
                                        countMax = loop + 1;

                                    }
                                }

                            }
                        }
                    }
                    if (countMax > finalMax)
                    {
                        finalMax = countMax;
                    }
                }
            }
            Console.WriteLine(finalMax);
        }
    }
}

Measured memory_bytes: 13268