import sys

import numpy as np

from heapq import heappop, heappush

read = sys.stdin.buffer.read

readline = sys.stdin.buffer.readline

readlines = sys.stdin.buffer.readlines

 



 

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

grid = np.full((H+2,W+2),b'#',dtype='S1')

grid[1:-1,1:-1] = np.frombuffer(read(),'S1').reshape(H,-1)[:,:W]

INF = 400

def shortest(grid, start, cost=0):

    dist = np.array([[INF for _ in range(W+2)] for _ in range(H+2)])

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

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

    st = [(cost, start)]

    dist[start[0]][start[1]]=0

    while(st):

        c, [sx, sy] = heappop(st)

        for a, b in zip(dx, dy):

            x = sx + a

            y = sy + b

            if grid[x][y]==b'#':

              continue

            dxy = dist[sx][sy] + 1

            if dist[x][y] <= dxy:

                continue

            dist[x][y] = dxy

            heappush(st, (dist[x][y], [x, y]))

    return np.max(dist[dist<INF])



m=0

for i in range(1,H+1):

  for j in range(1,W+1):

    if grid[i,j]==b'#':

      continue

    tm = shortest(grid, [i, j])

    if m < tm:

      m=tm

print(m)
import sys

from heapq import heappop, heappush

readline = sys.stdin.readline





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

grid = '#' * (W + 2) + ''.join('#' + readline().strip() +

                               '#' for _ in range(H)) + '#' * (W + 2)

INF = 400





def shortest(grid, start, cost=0):

    dist = [INF] * (H + 2) * (W + 2)

    move = (-1, 1, W + 2, -W - 2)

    st = [start]

    dist[start] = 0

    while(st):

        sx = heappop(st)

        c = dist[sx]

        for a in move:

            x = sx + a

            if grid[x] == '#':

                continue

            dx = dist[sx] + 1

            if dist[x] <= dx:

                continue

            dist[x] = dx

            heappush(st, x)

    return max(x for x in dist if x < INF)





m = 0

for i in range(W + 3, (H + 1) * (W + 2) - 1):

    if grid[i] == '#':

        continue

    tm = shortest(grid, i)

    if m < tm:

        m = tm

print(m)

import sys
import numpy as np
from heapq import heappop, heappush

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
H, W = list(map(int, readline().split()))
grid = np.full((H + 2, W + 2), b"#", dtype="S1")
grid[1:-1, 1:-1] = np.frombuffer(read(), "S1").reshape(H, -1)[:, :W]
INF = 400


def shortest(grid, start, cost=0):
    dist = np.array([[INF for _ in range(W + 2)] for _ in range(H + 2)])
    dx = [-1, 0, 1, 0]
    dy = [0, 1, 0, -1]
    st = [(cost, start)]
    dist[start[0]][start[1]] = 0
    while st:
        c, [sx, sy] = heappop(st)
        for a, b in zip(dx, dy):
            x = sx + a
            y = sy + b
            if grid[x][y] == b"#":
                continue
            dxy = dist[sx][sy] + 1
            if dist[x][y] <= dxy:
                continue
            dist[x][y] = dxy
            heappush(st, (dist[x][y], [x, y]))
    return np.max(dist[dist < INF])


m = 0
for i in range(1, H + 1):
    for j in range(1, W + 1):
        if grid[i, j] == b"#":
            continue
        tm = shortest(grid, [i, j])
        if m < tm:
            m = tm
print(m)

import sys
from heapq import heappop, heappush

readline = sys.stdin.readline
H, W = list(map(int, readline().split()))
grid = (
    "#" * (W + 2)
    + "".join("#" + readline().strip() + "#" for _ in range(H))
    + "#" * (W + 2)
)
INF = 400


def shortest(grid, start, cost=0):
    dist = [INF] * (H + 2) * (W + 2)
    move = (-1, 1, W + 2, -W - 2)
    st = [start]
    dist[start] = 0
    while st:
        sx = heappop(st)
        c = dist[sx]
        for a in move:
            x = sx + a
            if grid[x] == "#":
                continue
            dx = dist[sx] + 1
            if dist[x] <= dx:
                continue
            dist[x] = dx
            heappush(st, x)
    return max(x for x in dist if x < INF)


m = 0
for i in range(W + 3, (H + 1) * (W + 2) - 1):
    if grid[i] == "#":
        continue
    tm = shortest(grid, i)
    if m < tm:
        m = tm
print(m)

-import numpy as np -read = sys.stdin.buffer.read -readline = sys.stdin.buffer.readline -readlines = sys.stdin.buffer.readlines +readline = sys.stdin.readline -grid = np.full((H + 2, W + 2), b"#", dtype="S1") -grid[1:-1, 1:-1] = np.frombuffer(read(), "S1").reshape(H, -1)[:, :W] +grid = ( +    "#" * (W + 2) +    + "".join("#" + readline().strip() + "#" for _ in range(H)) +    + "#" * (W + 2) +) -    dist = np.array([[INF for _ in range(W + 2)] for _ in range(H + 2)]) -    dx = [-1, 0, 1, 0] -    dy = [0, 1, 0, -1] -    st = [(cost, start)] -    dist[start[0]][start[1]] = 0 +    dist = [INF] * (H + 2) * (W + 2) +    move = (-1, 1, W + 2, -W - 2) +    st = [start] +    dist[start] = 0 -        c, [sx, sy] = heappop(st) -        for a, b in zip(dx, dy): +        sx = heappop(st) +        c = dist[sx] +        for a in move: -            y = sy + b -            if grid[x][y] == b"#": +            if grid[x] == "#": -            dxy = dist[sx][sy] + 1 -            if dist[x][y] <= dxy: +            dx = dist[sx] + 1 +            if dist[x] <= dx: -            dist[x][y] = dxy -            heappush(st, (dist[x][y], [x, y])) -    return np.max(dist[dist < INF]) +            dist[x] = dx +            heappush(st, x) +    return max(x for x in dist if x < INF) -for i in range(1, H + 1): -    for j in range(1, W + 1): -        if grid[i, j] == b"#": -            continue -        tm = shortest(grid, [i, j]) -        if m < tm: -            m = tm +for i in range(W + 3, (H + 1) * (W + 2) - 1): +    if grid[i] == "#": +        continue +    tm = shortest(grid, i) +    if m < tm: +        m = tm