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

S=[[] for _ in range(H)]



for i in range(H):

    S[i]=eval(input())

    

def warshall_floyd(d):

    #d[i][j]: iからjへの最短距離

    for k in range(n):

        for i in range(n):

            for j in range(n):

                d[i][j] = min(d[i][j],d[i][k] + d[k][j])

    return d



n=H*W

inf=10**9



d = [[inf]*n for _ in range(n)] 

#d[u][v] : 辺uvのコスト(存在しないときはinf)

for i in range(H):

    for j in range(W):

        if S[i][j]==".":

            if j+1<W:

                if S[i][j+1]==".":

                    d[i*W+j][i*W+j+1]=1

                    d[i*W+j+1][i*W+j]=1

            if i+1<H:

                if S[i+1][j]==".":

                    d[i*W+j][(i+1)*W+j]=1

                    d[(i+1)*W+j][i*W+j]=1

    

        

for i in range(n):

    d[i][i] = 0 #自身のところに行くコストは０

ans=0



warshall_floyd(d)



for i in range(n):

    for j in range(n):

        if d[i][j]>=ans and d[i][j]<=inf-10:

            ans=d[i][j]



print(ans)
import queue



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

S=[[] for _ in range(H)]



dx=[0,0,-1,1]

dy=[-1,1,0,0]



for i in range(H):

    S[i]=eval(input())



def bfs(i,j):

    max_d=0

    q=queue.Queue()

    q.put((i,j))

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

    while not q.empty():

        loc=q.get()

        for k in range(len(dx)):

            x=loc[1]+dx[k]

            y=loc[0]+dy[k]

            if x>=0 and x<W and y>=0 and y<H:

                if S[y][x]==".":

                    if d[y][x]==0 and not(x==j and y==i):

                        q.put((y,x))

                        d[y][x]=d[loc[0]][loc[1]]+1

                        max_d=max(max_d,d[y][x])

    return max_d



ans=0

for i in range(H):

    for j in range(W):

        if S[i][j]==".":

            ans=max(bfs(i,j),ans)

        

print(ans)
H, W = list(map(int, input().split()))
S = [[] for _ in range(H)]
for i in range(H):
    S[i] = eval(input())


def warshall_floyd(d):
    # d[i][j]: iからjへの最短距離
    for k in range(n):
        for i in range(n):
            for j in range(n):
                d[i][j] = min(d[i][j], d[i][k] + d[k][j])
    return d


n = H * W
inf = 10**9
d = [[inf] * n for _ in range(n)]
# d[u][v] : 辺uvのコスト(存在しないときはinf)
for i in range(H):
    for j in range(W):
        if S[i][j] == ".":
            if j + 1 < W:
                if S[i][j + 1] == ".":
                    d[i * W + j][i * W + j + 1] = 1
                    d[i * W + j + 1][i * W + j] = 1
            if i + 1 < H:
                if S[i + 1][j] == ".":
                    d[i * W + j][(i + 1) * W + j] = 1
                    d[(i + 1) * W + j][i * W + j] = 1
for i in range(n):
    d[i][i] = 0  # 自身のところに行くコストは０
ans = 0
warshall_floyd(d)
for i in range(n):
    for j in range(n):
        if d[i][j] >= ans and d[i][j] <= inf - 10:
            ans = d[i][j]
print(ans)

import queue

H, W = list(map(int, input().split()))
S = [[] for _ in range(H)]
dx = [0, 0, -1, 1]
dy = [-1, 1, 0, 0]
for i in range(H):
    S[i] = eval(input())


def bfs(i, j):
    max_d = 0
    q = queue.Queue()
    q.put((i, j))
    d = [[0] * W for _ in range(H)]
    while not q.empty():
        loc = q.get()
        for k in range(len(dx)):
            x = loc[1] + dx[k]
            y = loc[0] + dy[k]
            if x >= 0 and x < W and y >= 0 and y < H:
                if S[y][x] == ".":
                    if d[y][x] == 0 and not (x == j and y == i):
                        q.put((y, x))
                        d[y][x] = d[loc[0]][loc[1]] + 1
                        max_d = max(max_d, d[y][x])
    return max_d


ans = 0
for i in range(H):
    for j in range(W):
        if S[i][j] == ".":
            ans = max(bfs(i, j), ans)
print(ans)

+import queue + +dx = [0, 0, -1, 1] +dy = [-1, 1, 0, 0] -def warshall_floyd(d): -    # d[i][j]: iからjへの最短距離 -    for k in range(n): -        for i in range(n): -            for j in range(n): -                d[i][j] = min(d[i][j], d[i][k] + d[k][j]) -    return d +def bfs(i, j): +    max_d = 0 +    q = queue.Queue() +    q.put((i, j)) +    d = [[0] * W for _ in range(H)] +    while not q.empty(): +        loc = q.get() +        for k in range(len(dx)): +            x = loc[1] + dx[k] +            y = loc[0] + dy[k] +            if x >= 0 and x < W and y >= 0 and y < H: +                if S[y][x] == ".": +                    if d[y][x] == 0 and not (x == j and y == i): +                        q.put((y, x)) +                        d[y][x] = d[loc[0]][loc[1]] + 1 +                        max_d = max(max_d, d[y][x]) +    return max_d -n = H * W -inf = 10**9 -d = [[inf] * n for _ in range(n)] -# d[u][v] : 辺uvのコスト(存在しないときはinf) +ans = 0 -            if j + 1 < W: -                if S[i][j + 1] == ".": -                    d[i * W + j][i * W + j + 1] = 1 -                    d[i * W + j + 1][i * W + j] = 1 -            if i + 1 < H: -                if S[i + 1][j] == ".": -                    d[i * W + j][(i + 1) * W + j] = 1 -                    d[(i + 1) * W + j][i * W + j] = 1 -for i in range(n): -    d[i][i] = 0  # 自身のところに行くコストは０ -ans = 0 -warshall_floyd(d) -for i in range(n): -    for j in range(n): -        if d[i][j] >= ans and d[i][j] <= inf - 10: -            ans = d[i][j] +            ans = max(bfs(i, j), ans)