from copy import deepcopy





def solve(maze, i, j, h, w, count):

    distance = 0

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

        distance = 0

        next_search = [(i, j)]

        while not next_search == []:

            now = next_search.pop(0)

            if maze[now[0]][now[1]] == ".":

                maze[now[0]][now[1]] = "#"

                for direction in [(1, 0), (-1, 0), (0, 1), (0, -1)]:

                    search = [direction[0] + now[0], direction[1] + now[1]]

                    if search[0] < 0 or h <= search[0] or search[1] < 0 or w <= search[1] or \

                            maze[search[0]][search[1]] == "#":

                        continue

                    else:

                        count[search[0]][search[1]] = count[now[0]][now[1]] + 1

                        next_search.append(tuple(search))

                        distance = max(distance, count[search[0]][search[1]])

    return distance





def main():

    height, width = map(int, input().split(" "))

    maze = []

    answer = 0

    for _ in range(height):

        maze.append(list(input()))

    count = [[0 for _ in range(width)] for _ in range(height)]

    for i in range(height):

        for j in range(width):

            answer = max(answer, solve(deepcopy(maze), i, j, height, width, deepcopy(count)))

    print(answer)





if __name__ == '__main__':

    main()



from collections import deque

from copy import deepcopy





def main():

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

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

    ans = 0

    d = [[0, 1], [1, 0], [0, -1], [-1, 0]]

    for i in range(h):

        for j in range(w):

            if grid[i][j] == "#":

                continue

            now_grid = deepcopy(grid)

            answer = [[float("inf") for _ in range(w)] for _ in range(h)]

            next = deque([[i, j]])

            answer[i][j] = 0

            while next:

                y, x = next.popleft()

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

                    now_grid[y][x] = "#"

                    for dx, dy in d:

                        if 0 <= x + dx < w and 0 <= y + dy < h and now_grid[y + dy][x + dx] == ".":

                            answer[y + dy][x + dx] = min(answer[y][x] + 1, answer[y + dy][x + dx])

                            next.append([y + dy, x + dx])

            for k in range(h):

                for l in range(w):

                    if grid[k][l] == "#":

                        continue

                    ans = max(ans, answer[k][l])

    print(ans)





if __name__ == '__main__':

    main()



from copy import deepcopy


def solve(maze, i, j, h, w, count):
    distance = 0
    if maze[i][j] == ".":
        distance = 0
        next_search = [(i, j)]
        while not next_search == []:
            now = next_search.pop(0)
            if maze[now[0]][now[1]] == ".":
                maze[now[0]][now[1]] = "#"
                for direction in [(1, 0), (-1, 0), (0, 1), (0, -1)]:
                    search = [direction[0] + now[0], direction[1] + now[1]]
                    if (
                        search[0] < 0
                        or h <= search[0]
                        or search[1] < 0
                        or w <= search[1]
                        or maze[search[0]][search[1]] == "#"
                    ):
                        continue
                    else:
                        count[search[0]][search[1]] = count[now[0]][now[1]] + 1
                        next_search.append(tuple(search))
                        distance = max(distance, count[search[0]][search[1]])
    return distance


def main():
    height, width = map(int, input().split(" "))
    maze = []
    answer = 0
    for _ in range(height):
        maze.append(list(input()))
    count = [[0 for _ in range(width)] for _ in range(height)]
    for i in range(height):
        for j in range(width):
            answer = max(
                answer, solve(deepcopy(maze), i, j, height, width, deepcopy(count))
            )
    print(answer)


if __name__ == "__main__":
    main()

from collections import deque
from copy import deepcopy


def main():
    h, w = list(map(int, input().split()))
    grid = [list(eval(input())) for _ in range(h)]
    ans = 0
    d = [[0, 1], [1, 0], [0, -1], [-1, 0]]
    for i in range(h):
        for j in range(w):
            if grid[i][j] == "#":
                continue
            now_grid = deepcopy(grid)
            answer = [[float("inf") for _ in range(w)] for _ in range(h)]
            next = deque([[i, j]])
            answer[i][j] = 0
            while next:
                y, x = next.popleft()
                if now_grid[y][x] == ".":
                    now_grid[y][x] = "#"
                    for dx, dy in d:
                        if (
                            0 <= x + dx < w
                            and 0 <= y + dy < h
                            and now_grid[y + dy][x + dx] == "."
                        ):
                            answer[y + dy][x + dx] = min(
                                answer[y][x] + 1, answer[y + dy][x + dx]
                            )
                            next.append([y + dy, x + dx])
            for k in range(h):
                for l in range(w):
                    if grid[k][l] == "#":
                        continue
                    ans = max(ans, answer[k][l])
    print(ans)


if __name__ == "__main__":
    main()

+from collections import deque -def solve(maze, i, j, h, w, count): -    distance = 0 -    if maze[i][j] == ".": -        distance = 0 -        next_search = [(i, j)] -        while not next_search == []: -            now = next_search.pop(0) -            if maze[now[0]][now[1]] == ".": -                maze[now[0]][now[1]] = "#" -                for direction in [(1, 0), (-1, 0), (0, 1), (0, -1)]: -                    search = [direction[0] + now[0], direction[1] + now[1]] -                    if ( -                        search[0] < 0 -                        or h <= search[0] -                        or search[1] < 0 -                        or w <= search[1] -                        or maze[search[0]][search[1]] == "#" -                    ): +def main(): +    h, w = list(map(int, input().split())) +    grid = [list(eval(input())) for _ in range(h)] +    ans = 0 +    d = [[0, 1], [1, 0], [0, -1], [-1, 0]] +    for i in range(h): +        for j in range(w): +            if grid[i][j] == "#": +                continue +            now_grid = deepcopy(grid) +            answer = [[float("inf") for _ in range(w)] for _ in range(h)] +            next = deque([[i, j]]) +            answer[i][j] = 0 +            while next: +                y, x = next.popleft() +                if now_grid[y][x] == ".": +                    now_grid[y][x] = "#" +                    for dx, dy in d: +                        if ( +                            0 <= x + dx < w +                            and 0 <= y + dy < h +                            and now_grid[y + dy][x + dx] == "." +                        ): +                            answer[y + dy][x + dx] = min( +                                answer[y][x] + 1, answer[y + dy][x + dx] +                            ) +                            next.append([y + dy, x + dx]) +            for k in range(h): +                for l in range(w): +                    if grid[k][l] == "#": -                    else: -                        count[search[0]][search[1]] = count[now[0]][now[1]] + 1 -                        next_search.append(tuple(search)) -                        distance = max(distance, count[search[0]][search[1]]) -    return distance - - -def main(): -    height, width = map(int, input().split(" ")) -    maze = [] -    answer = 0 -    for _ in range(height): -        maze.append(list(input())) -    count = [[0 for _ in range(width)] for _ in range(height)] -    for i in range(height): -        for j in range(width): -            answer = max( -                answer, solve(deepcopy(maze), i, j, height, width, deepcopy(count)) -            ) -    print(answer) +                    ans = max(ans, answer[k][l]) +    print(ans)