from collections import deque

import numpy as np



H,W = list(map(int,input().split()))

maze = [eval(input()) for _ in range(H)]#迷路の入力



ans = 0

for x in range(H):#すべてのマスからスタート

    for y in range(W):

        #壁からはスタートできない：スルー

        if maze[x][y] == "#":

            continue



        #初期化：0埋め、HとWの順番に注意

        distance = [[0]*W for _ in range(H)]

        #start位置

        stack = deque([[x,y]])#デキューに入れる



        while stack:#スタックが有るあいだ

            h,w = stack.popleft()#スタックの先頭を取ってくる

            for i,j in [[1,0],[-1,0],[0,1],[0,-1]]:#マスの四方

                new_h, new_w = h+i, w+j#新しいマス

                if new_h < 0 or new_w < 0 or new_h >= H or new_w >= W:

                    continue#範囲外ならスルー

                elif maze[new_h][new_w] != "#" and distance[new_h][new_w] == 0:

                    distance[new_h][new_w] = distance[h][w]+1#BFS、+1

                    stack.append([new_h, new_w])#新しいマスをスタックへ



        #start位置は0で初期化

        distance[x][y] = 0

        ans = max(ans, np.max(distance))#npは二次元のmax取れる



print(ans)
'''ika tako

スタートが決められたとき、そこから最も遠いマスは、

幅優先探索で最後に訪れたマスとなる。

よって、道である各マスをスタート地点として全て試し、

最長移動距離の最大値が答え。

H,W  の上限が小さいので、スタート地点候補が最大400、

1回の探索で探索するマスが最大400、あわせて160000回に

比例する計算量で間に合う。

'''

from collections import deque

 

def bfs(field, s):

    MOVE = [(0, 1), (1, 0), (0, -1), (-1, 0)]

    q = deque([(0, s)])

    dist = [[-1] * w for _ in range(h)]

 

    d, i, j = -1, -1, -1

    while q:

        d, (i, j) = q.popleft()

        if dist[i][j] != -1:

            continue

        dist[i][j] = d

        for di, dj in MOVE:

            ni, nj = i + di, j + dj

            if not 0 <= ni < h or not 0 <= nj < w:

                continue

            if field[ni][nj] == '#':

                continue

            if dist[ni][nj] != -1:

                continue

            q.append((d + 1, (ni, nj)))

    return d, i, j



h, w = list(map(int, input().split()))

field = [eval(input()) for _ in range(h)]

ans = 0

for i in range(h):

    for j in range(w):

        if field[i][j] == '.':

            d, i, j = bfs(field, (i, j))

            ans = max(ans, d)

print(ans)
from collections import deque
import numpy as np

H, W = list(map(int, input().split()))
maze = [eval(input()) for _ in range(H)]  # 迷路の入力
ans = 0
for x in range(H):  # すべてのマスからスタート
    for y in range(W):
        # 壁からはスタートできない：スルー
        if maze[x][y] == "#":
            continue
        # 初期化：0埋め、HとWの順番に注意
        distance = [[0] * W for _ in range(H)]
        # start位置
        stack = deque([[x, y]])  # デキューに入れる
        while stack:  # スタックが有るあいだ
            h, w = stack.popleft()  # スタックの先頭を取ってくる
            for i, j in [[1, 0], [-1, 0], [0, 1], [0, -1]]:  # マスの四方
                new_h, new_w = h + i, w + j  # 新しいマス
                if new_h < 0 or new_w < 0 or new_h >= H or new_w >= W:
                    continue  # 範囲外ならスルー
                elif maze[new_h][new_w] != "#" and distance[new_h][new_w] == 0:
                    distance[new_h][new_w] = distance[h][w] + 1  # BFS、+1
                    stack.append([new_h, new_w])  # 新しいマスをスタックへ
        # start位置は0で初期化
        distance[x][y] = 0
        ans = max(ans, np.max(distance))  # npは二次元のmax取れる
print(ans)

"""ika tako
スタートが決められたとき、そこから最も遠いマスは、
幅優先探索で最後に訪れたマスとなる。
よって、道である各マスをスタート地点として全て試し、
最長移動距離の最大値が答え。
H,W  の上限が小さいので、スタート地点候補が最大400、
1回の探索で探索するマスが最大400、あわせて160000回に
比例する計算量で間に合う。
"""
from collections import deque


def bfs(field, s):
    MOVE = [(0, 1), (1, 0), (0, -1), (-1, 0)]
    q = deque([(0, s)])
    dist = [[-1] * w for _ in range(h)]
    d, i, j = -1, -1, -1
    while q:
        d, (i, j) = q.popleft()
        if dist[i][j] != -1:
            continue
        dist[i][j] = d
        for di, dj in MOVE:
            ni, nj = i + di, j + dj
            if not 0 <= ni < h or not 0 <= nj < w:
                continue
            if field[ni][nj] == "#":
                continue
            if dist[ni][nj] != -1:
                continue
            q.append((d + 1, (ni, nj)))
    return d, i, j


h, w = list(map(int, input().split()))
field = [eval(input()) for _ in range(h)]
ans = 0
for i in range(h):
    for j in range(w):
        if field[i][j] == ".":
            d, i, j = bfs(field, (i, j))
            ans = max(ans, d)
print(ans)

+"""ika tako +スタートが決められたとき、そこから最も遠いマスは、 +幅優先探索で最後に訪れたマスとなる。 +よって、道である各マスをスタート地点として全て試し、 +最長移動距離の最大値が答え。 +H,W  の上限が小さいので、スタート地点候補が最大400、 +1回の探索で探索するマスが最大400、あわせて160000回に +比例する計算量で間に合う。 +""" -import numpy as np -H, W = list(map(int, input().split())) -maze = [eval(input()) for _ in range(H)]  # 迷路の入力 + +def bfs(field, s): +    MOVE = [(0, 1), (1, 0), (0, -1), (-1, 0)] +    q = deque([(0, s)]) +    dist = [[-1] * w for _ in range(h)] +    d, i, j = -1, -1, -1 +    while q: +        d, (i, j) = q.popleft() +        if dist[i][j] != -1: +            continue +        dist[i][j] = d +        for di, dj in MOVE: +            ni, nj = i + di, j + dj +            if not 0 <= ni < h or not 0 <= nj < w: +                continue +            if field[ni][nj] == "#": +                continue +            if dist[ni][nj] != -1: +                continue +            q.append((d + 1, (ni, nj))) +    return d, i, j + + +h, w = list(map(int, input().split())) +field = [eval(input()) for _ in range(h)] -for x in range(H):  # すべてのマスからスタート -    for y in range(W): -        # 壁からはスタートできない：スルー -        if maze[x][y] == "#": -            continue -        # 初期化：0埋め、HとWの順番に注意 -        distance = [[0] * W for _ in range(H)] -        # start位置 -        stack = deque([[x, y]])  # デキューに入れる -        while stack:  # スタックが有るあいだ -            h, w = stack.popleft()  # スタックの先頭を取ってくる -            for i, j in [[1, 0], [-1, 0], [0, 1], [0, -1]]:  # マスの四方 -                new_h, new_w = h + i, w + j  # 新しいマス -                if new_h < 0 or new_w < 0 or new_h >= H or new_w >= W: -                    continue  # 範囲外ならスルー -                elif maze[new_h][new_w] != "#" and distance[new_h][new_w] == 0: -                    distance[new_h][new_w] = distance[h][w] + 1  # BFS、+1 -                    stack.append([new_h, new_w])  # 新しいマスをスタックへ -        # start位置は0で初期化 -        distance[x][y] = 0 -        ans = max(ans, np.max(distance))  # npは二次元のmax取れる +for i in range(h): +    for j in range(w): +        if field[i][j] == ".": +            d, i, j = bfs(field, (i, j)) +            ans = max(ans, d)