#python3

from collections import deque         

INF = int(1e9)

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



def main():

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

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

    ans = -1 

    

    for i in range(h):

        for j in range(w):

            if maze[i][j] == '#':

                continue

            g = [[INF for _ in range(w)] for _ in range(h)] 

            q = deque()

            q.append((i, j))

            g[i][j] = 0

            while len(q) > 0:

                pi, pj = q.popleft()

                for dx, dy in dd:

                    x = pi + dx

                    y = pj + dy

                    if (x < 0) | (y < 0) | (x >= h) | (y >= w): 

                        continue

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

                        continue

                    if g[x][y] != INF:

                        continue

                    q.append((x, y))

                    g[x][y] = g[pi][pj]+1 

            



            for k in range(h):

                for l in range(w):

                    if g[k][l] == INF:

                        continue

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

    print(ans)

main()
import sys

read = sys.stdin.buffer.read

readline = sys.stdin.buffer.readline

readlines = sys.stdin.buffer.readlines

from collections import deque 

INF = 100000

dir = ((1, 0), (-1, 0), (0, 1), (0, -1)) 

def main():

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

    maze = []

    for _ in range(H):

        s = readline().rstrip().decode()

        maze.append(s) 

    

    

    def bfs(si, sj):

        dq = deque()

        dq.append((si, sj))        

        dist = [[INF for _ in range(W)] for _ in range(H)]

        dist[si][sj] = 0

        while len(dq)>0:

            i, j = dq.popleft()

            for di, dj in dir:

                nxi = i+di

                nxj = j+dj

                if (nxi<0) or (nxj<0) or (nxi>=H) or (nxj>=W):

                    continue

                if maze[nxi][nxj] == '#':

                    continue

                if dist[nxi][nxj] != INF:

                    continue

                dist[nxi][nxj] = dist[i][j]+1

                dq.append((nxi, nxj))

        res = 0

        for i in range(H):

            for j in range(W):

                if dist[i][j] == INF:

                    continue

                res = max(dist[i][j], res)        

        return res



    ans = 0

    for si in range(H):

        for sj in range(W):

            if maze[si][sj] == '#':

                continue

            ans = max(bfs(si, sj), ans)



    print(ans)



if __name__ == '__main__':

    main()

# python3
from collections import deque

INF = int(1e9)
dd = [(-1, 0), (1, 0), (0, 1), (0, -1)]


def main():
    h, w = list(map(int, input().split()))
    maze = [eval(input()) for _ in range(h)]
    ans = -1
    for i in range(h):
        for j in range(w):
            if maze[i][j] == "#":
                continue
            g = [[INF for _ in range(w)] for _ in range(h)]
            q = deque()
            q.append((i, j))
            g[i][j] = 0
            while len(q) > 0:
                pi, pj = q.popleft()
                for dx, dy in dd:
                    x = pi + dx
                    y = pj + dy
                    if (x < 0) | (y < 0) | (x >= h) | (y >= w):
                        continue
                    if maze[x][y] == "#":
                        continue
                    if g[x][y] != INF:
                        continue
                    q.append((x, y))
                    g[x][y] = g[pi][pj] + 1
            for k in range(h):
                for l in range(w):
                    if g[k][l] == INF:
                        continue
                    ans = max(ans, g[k][l])
    print(ans)


main()

import sys

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
from collections import deque

INF = 100000
dir = ((1, 0), (-1, 0), (0, 1), (0, -1))


def main():
    H, W = list(map(int, readline().split()))
    maze = []
    for _ in range(H):
        s = readline().rstrip().decode()
        maze.append(s)

    def bfs(si, sj):
        dq = deque()
        dq.append((si, sj))
        dist = [[INF for _ in range(W)] for _ in range(H)]
        dist[si][sj] = 0
        while len(dq) > 0:
            i, j = dq.popleft()
            for di, dj in dir:
                nxi = i + di
                nxj = j + dj
                if (nxi < 0) or (nxj < 0) or (nxi >= H) or (nxj >= W):
                    continue
                if maze[nxi][nxj] == "#":
                    continue
                if dist[nxi][nxj] != INF:
                    continue
                dist[nxi][nxj] = dist[i][j] + 1
                dq.append((nxi, nxj))
        res = 0
        for i in range(H):
            for j in range(W):
                if dist[i][j] == INF:
                    continue
                res = max(dist[i][j], res)
        return res

    ans = 0
    for si in range(H):
        for sj in range(W):
            if maze[si][sj] == "#":
                continue
            ans = max(bfs(si, sj), ans)
    print(ans)


if __name__ == "__main__":
    main()

-# python3 +import sys + +read = sys.stdin.buffer.read +readline = sys.stdin.buffer.readline +readlines = sys.stdin.buffer.readlines -INF = int(1e9) -dd = [(-1, 0), (1, 0), (0, 1), (0, -1)] +INF = 100000 +dir = ((1, 0), (-1, 0), (0, 1), (0, -1)) -    h, w = list(map(int, input().split())) -    maze = [eval(input()) for _ in range(h)] -    ans = -1 -    for i in range(h): -        for j in range(w): -            if maze[i][j] == "#": +    H, W = list(map(int, readline().split())) +    maze = [] +    for _ in range(H): +        s = readline().rstrip().decode() +        maze.append(s) + +    def bfs(si, sj): +        dq = deque() +        dq.append((si, sj)) +        dist = [[INF for _ in range(W)] for _ in range(H)] +        dist[si][sj] = 0 +        while len(dq) > 0: +            i, j = dq.popleft() +            for di, dj in dir: +                nxi = i + di +                nxj = j + dj +                if (nxi < 0) or (nxj < 0) or (nxi >= H) or (nxj >= W): +                    continue +                if maze[nxi][nxj] == "#": +                    continue +                if dist[nxi][nxj] != INF: +                    continue +                dist[nxi][nxj] = dist[i][j] + 1 +                dq.append((nxi, nxj)) +        res = 0 +        for i in range(H): +            for j in range(W): +                if dist[i][j] == INF: +                    continue +                res = max(dist[i][j], res) +        return res + +    ans = 0 +    for si in range(H): +        for sj in range(W): +            if maze[si][sj] == "#": -            g = [[INF for _ in range(w)] for _ in range(h)] -            q = deque() -            q.append((i, j)) -            g[i][j] = 0 -            while len(q) > 0: -                pi, pj = q.popleft() -                for dx, dy in dd: -                    x = pi + dx -                    y = pj + dy -                    if (x < 0) | (y < 0) | (x >= h) | (y >= w): -                        continue -                    if maze[x][y] == "#": -                        continue -                    if g[x][y] != INF: -                        continue -                    q.append((x, y)) -                    g[x][y] = g[pi][pj] + 1 -            for k in range(h): -                for l in range(w): -                    if g[k][l] == INF: -                        continue -                    ans = max(ans, g[k][l]) +            ans = max(bfs(si, sj), ans) -main() +if __name__ == "__main__": +    main()