# D - Maze Master

from collections import deque, defaultdict



INF = 1 << 30

MOD = 10 ** 9 + 7

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





def bfs(sx: int, sy: int):

    queue = deque([(sx, sy)])

    dist = defaultdict(lambda: INF)

    dist[sx * MOD + sy] = 0

    while queue:

        x, y = queue.popleft()

        for dx, dy in dxy:

            nx, ny = x + dx, y + dy

            if S[nx][ny] == "." and dist[x * MOD + y] + 1 < dist[nx * MOD + ny]:

                dist[nx * MOD + ny] = dist[x * MOD + y] + 1

                queue.append((nx, ny))

    return max(dist.values())





def main():

    global S

    H, W, *S = open(0).read().split()

    H, W = int(H) + 2, int(W) + 2

    S = ["#" * W] + ["#" + s + "#" for s in S] + ["#" * W]  # put sentinels

    ans = max(bfs(i, j) for i, s in enumerate(S) for j, c in enumerate(s) if c == ".")

    print(ans)





if __name__ == "__main__":

    main()

# D - Maze Master

from collections import deque, defaultdict



INF = 1 << 30

MOD = 10 ** 9 + 7

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





def bfs(sx: int, sy: int):

    queue = deque([(sx, sy)])

    dist = defaultdict(lambda: INF)

    dist[sx * MOD + sy] = 0

    while queue:

        x, y = queue.popleft()

        for dx, dy in dxy:

            nx, ny = x + dx, y + dy

            if S[nx][ny] == ".":

                if nx * MOD + ny not in dist:

                    dist[nx * MOD + ny] = dist[x * MOD + y] + 1

                    queue.append((nx, ny))

    return max(dist.values())





def main():

    global S

    H, W, *S = open(0).read().split()

    H, W = int(H) + 2, int(W) + 2

    S = ["#" * W] + ["#" + s + "#" for s in S] + ["#" * W]  # put sentinels

    ans = max(bfs(i, j) for i, s in enumerate(S) for j, c in enumerate(s) if c == ".")

    print(ans)





if __name__ == "__main__":

    main()

# D - Maze Master
from collections import deque, defaultdict

INF = 1 << 30
MOD = 10**9 + 7
dxy = [(-1, 0), (0, -1), (0, 1), (1, 0)]


def bfs(sx: int, sy: int):
    queue = deque([(sx, sy)])
    dist = defaultdict(lambda: INF)
    dist[sx * MOD + sy] = 0
    while queue:
        x, y = queue.popleft()
        for dx, dy in dxy:
            nx, ny = x + dx, y + dy
            if S[nx][ny] == "." and dist[x * MOD + y] + 1 < dist[nx * MOD + ny]:
                dist[nx * MOD + ny] = dist[x * MOD + y] + 1
                queue.append((nx, ny))
    return max(dist.values())


def main():
    global S
    H, W, *S = open(0).read().split()
    H, W = int(H) + 2, int(W) + 2
    S = ["#" * W] + ["#" + s + "#" for s in S] + ["#" * W]  # put sentinels
    ans = max(bfs(i, j) for i, s in enumerate(S) for j, c in enumerate(s) if c == ".")
    print(ans)


if __name__ == "__main__":
    main()

# D - Maze Master
from collections import deque, defaultdict

INF = 1 << 30
MOD = 10**9 + 7
dxy = [(-1, 0), (0, -1), (0, 1), (1, 0)]


def bfs(sx: int, sy: int):
    queue = deque([(sx, sy)])
    dist = defaultdict(lambda: INF)
    dist[sx * MOD + sy] = 0
    while queue:
        x, y = queue.popleft()
        for dx, dy in dxy:
            nx, ny = x + dx, y + dy
            if S[nx][ny] == ".":
                if nx * MOD + ny not in dist:
                    dist[nx * MOD + ny] = dist[x * MOD + y] + 1
                    queue.append((nx, ny))
    return max(dist.values())


def main():
    global S
    H, W, *S = open(0).read().split()
    H, W = int(H) + 2, int(W) + 2
    S = ["#" * W] + ["#" + s + "#" for s in S] + ["#" * W]  # put sentinels
    ans = max(bfs(i, j) for i, s in enumerate(S) for j, c in enumerate(s) if c == ".")
    print(ans)


if __name__ == "__main__":
    main()

-            if S[nx][ny] == "." and dist[x * MOD + y] + 1 < dist[nx * MOD + ny]: -                dist[nx * MOD + ny] = dist[x * MOD + y] + 1 -                queue.append((nx, ny)) +            if S[nx][ny] == ".": +                if nx * MOD + ny not in dist: +                    dist[nx * MOD + ny] = dist[x * MOD + y] + 1 +                    queue.append((nx, ny))