CodeEff/ECCO huggingface dataset:
# Original solution
import sys
input = sys.stdin.readline
from collections import deque


def main():
    H, W = [int(x) for x in input().split()]
    A = [["" for i in range(W)] for j in range(H)]

    for j in range(H):
        S = input().strip()
        for i, s in enumerate(list(S)):
            A[j][i] = s


    ma = 0

    dj = [1, 0, -1, 0]
    di = [0, 1, 0, -1]

    for sj in range(H):
        for si in range(W):
            for gj in range(H):
                for gi in range(W):
                    d = [[-1] * W for i in range(H)]
                    q = deque([])
                    q.append((sj, si))
                    d[sj][si] = 0

                    while q:
                        p = q.popleft()
                        if p[0] == gj and p[1] == gi:
                            break
                        for i in range(4):
                            nj = p[0] + dj[i]
                            ni = p[1] + di[i]

                            if 0 <= nj < H and 0 <= ni < W and A[nj][ni] != "#" and d[nj][ni] == -1:
                                q.append((nj, ni))
                                d[nj][ni] = d[p[0]][p[1]] + 1

                    ma = max(ma, d[gj][gi])



    print(ma)





    


if __name__ == '__main__':
    main()



# Optimized solution
import sys
input = sys.stdin.readline
from collections import deque


def main():
    H, W = [int(x) for x in input().split()]
    A = [["" for i in range(W)] for j in range(H)]

    for j in range(H):
        S = input().strip()
        for i, s in enumerate(list(S)):
            A[j][i] = s

    ma = 0

    dj = [1, 0, -1, 0]
    di = [0, 1, 0, -1]

    for sj in range(H):
        for si in range(W):
            if A[sj][si] == "#":
                continue
            d = [[-1 for i in range(W)] for j in range(H)]
            q = deque([])
            q.append((sj, si))
            d[sj][si] = 0

            while q:
                p = q.popleft()
                for i in range(4):
                    nj = p[0] + dj[i]
                    ni = p[1] + di[i]

                    if 0 <= nj < H and 0 <= ni < W and A[nj][ni] != "#" and d[nj][ni] == -1:
                        q.append((nj, ni))
                        d[nj][ni] = d[p[0]][p[1]] + 1

            for gj in range(H):
                for gi in range(W):
                    ma = max(ma, d[gj][gi])

    print(ma)





    


if __name__ == '__main__':
    main()
# Original solution
import sys
input = sys.stdin.readline
from collections import deque

H, W = list(map(int, input().split()))
S = [list(input().split()[0]) for _ in range(H)]

def bfs(S, H, W, start, goal):
    INF = 100000000
    stack=deque([start])
    distance = [[INF]*W for _ in range(H)]
    distance[start[1]][start[0]] = 0
    while stack:
        x, y = stack.popleft()
        if (x, y) == goal:
            break
        for i, j in [(1,0),(0,1),(-1,0),(0,-1)]:
            next_x = x + i
            next_y = y + j
            if not(0 <= next_x < W and 0 <= next_y < H):
                continue
            if S[next_y][next_x] != '#' and distance[next_y][next_x] == INF:
                stack.append([next_x, next_y])
                distance[next_y][next_x] = distance[y][x] + 1
    return distance[goal[1]][goal[0]]

ans = 0
for i in range(H):
    for j in range(W):
        for k in range(H):
            for l in range(W):
                if (i, j) == (k, l) or S[i][j] == "#" or S[k][l] == "#":
                    continue
                start = (j, i)
                goal = (l, k)
                ans = max(ans, bfs(S, H, W, start, goal))
print(ans)

# Optimized solution
import sys
input = sys.stdin.readline
from collections import deque

H, W = list(map(int, input().split()))
S = [list(input().split()[0]) for _ in range(H)]

def bfs(S, H, W, start):
    INF = -1
    stack=deque([start])
    distance = [[INF]*W for _ in range(H)]
    distance[start[1]][start[0]] = 0
    while stack:
        x, y = stack.popleft()
        for i, j in [(1,0),(0,1),(-1,0),(0,-1)]:
            next_x = x + i
            next_y = y + j
            if not(0 <= next_x < W and 0 <= next_y < H):
                continue
            if S[next_y][next_x] != '#' and distance[next_y][next_x] == -1:
                stack.append([next_x, next_y])
                distance[next_y][next_x] = distance[y][x] + 1
    return max(list(map(max, distance)))

ans = 0
for i in range(H):
    for j in range(W):
        if S[i][j] != "#":
            ans = max(ans, bfs(S, H, W, (j, i)))
print(ans)
# Original solution
from collections import deque 
from copy import deepcopy
# 初期入力
import sys
input = sys.stdin.readline
H,W = (int(i) for i in input().split())
map_initial =[["#"]*(W+2) for i in range(H+2)] #周囲を壁にするため＋２
for h in range(1,H+1):
    map_initial[h] =["#"] +list(input().strip()) +["#"]

def BSF(x,y):
    dist =0
    map =deepcopy(map_initial)
    if map[x][y] =="#":
        return dist 
    dq =deque()
    dq.append((x,y))
    dq_sarch =deque()
    while len(dq) >0:
        h,w =dq.popleft()
        map[h][w] ="#" #通り済を壁にする
        if map[h+1][w]==".":
            dq_sarch.append((h+1,w))
        if map[h-1][w]==".":
            dq_sarch.append((h-1,w))
        if map[h][w+1]==".":
            dq_sarch.append((h,w+1))
        if map[h][w-1]==".":
            dq_sarch.append((h,w-1))
        if len(dq)==0:
            dq =deepcopy(dq_sarch)
            dq_sarch.clear()
            dist +=1
        #print(h,w,dist,end="\t")
    return dist-1

#スタート位置を全探索し、最長距離を探す
dist_all =[]
for i in range(1,H+1):
    for j in range(1,W+1):
        dist_all.append(BSF(i,j) )
print((max(dist_all)))

# Optimized solution
from collections import deque 
from copy import deepcopy
# 初期入力
import sys
input = sys.stdin.readline
H,W = (int(i) for i in input().split())
map_initial =[["#"]*(W+2) for i in range(H+2)] #周囲を壁にするため＋２
for h in range(1,H+1):
    map_initial[h] =["#"] +list(input().strip()) +["#"]

def BSF(x,y):
    dist =0
    map =deepcopy(map_initial)
    if map[x][y] =="#":
        return dist 
    dq =set()
    dq.add((x,y))
    dq_sarch =set()
    while len(dq) >0:
        h,w =dq.pop()
        map[h][w] ="#" #通り済を壁にする
        if map[h+1][w]==".":
            dq_sarch.add((h+1,w))
        if map[h-1][w]==".":
            dq_sarch.add((h-1,w))
        if map[h][w+1]==".":
            dq_sarch.add((h,w+1))
        if map[h][w-1]==".":
            dq_sarch.add((h,w-1))
        if len(dq)==0:
            dq =deepcopy(dq_sarch)
            dq_sarch.clear()
            dist +=1
        #print(h,w,dist,end="\t")
    return dist-1

#スタート位置を全探索し、最長距離を探す
dist_all =[]
for i in range(1,H+1):
    for j in range(1,W+1):
        dist_all.append(BSF(i,j) )
print((max(dist_all)))
# Original solution
import queue
import sys

input = sys.stdin.readline


class Solution:
    def main(self):
        H, W = list(map(int, input().split()))
        S = [list(input().rstrip()) for _ in range(H)]

        for i in range(H):
            S[i] = ["#"] + S[i] + ["#"]
        S = [["#"] * (W + 2)] + S + [["#"] * (W + 2)]

        already = set()
        ans = 0
        for i in range(1, H + 1):
            for j in range(1, W + 1):
                if S[i][j] == "#":
                    continue
                for n in range(1, H + 1):
                    for m in range(1, W + 1):
                        if S[n][m] == "#" or (i, j) == (n, m) or (i, j, n, m) in already:
                            continue
                        v = self.min_move(S, (i, j), (n, m))
                        already.add((i, j, n, m))
                        already.add((n, m, i, j))
                        ans = max(ans, v)
        print(ans)

    def min_move(self, map, start, goal):
        moving_range = ((1, 0), (-1, 0), (0, 1), (0, -1))

        q = queue.Queue()
        q.put((start, 0))

        while not q.empty():
            pos, cnt = q.get()
            for move in moving_range:
                i, j = pos[0] + move[0], pos[1] + move[1]
                if (i, j) == goal:
                    return cnt + 1
                if map[i][j] == ".":
                    q.put(((i, j), cnt + 1))


# Run main
if __name__ == '__main__':
    Solution().main()


# Optimized solution
import queue
import sys

input = sys.stdin.readline


class Solution:
    def main(self):
        H, W = list(map(int, input().split()))
        S = [list(input().rstrip()) for _ in range(H)]

        for i in range(H):
            S[i] = ["#"] + S[i] + ["#"]
        S = [["#"] * (W + 2)] + S + [["#"] * (W + 2)]

        ans = 0
        for i in range(1, H + 1):
            for j in range(1, W + 1):
                if S[i][j] == "#":
                    continue
                v = self.min_move(S, (i, j))
                ans = max(ans, v)
        print(ans)

    def min_move(self, map, start):
        moving_range = ((1, 0), (-1, 0), (0, 1), (0, -1))

        q = queue.Queue()
        q.put((start, 0))

        already = {start}
        ret = 0
        while not q.empty():
            pos, cnt = q.get()
            ret = max(ret, cnt)
            for move in moving_range:
                i, j = pos[0] + move[0], pos[1] + move[1]
                if (i, j) not in already and map[i][j] == ".":
                    q.put(((i, j), cnt + 1))
                    already.add((i, j))

        return ret


# Run main
if __name__ == '__main__':
    Solution().main()
# Original solution
import sys
from queue import Queue


def print_costs(costs):
    for c in costs:
        print(c)


def solve(inp):
    (H, W) = list(map(int, inp.readline().strip().split(' ')))
    S = [list(inp.readline().strip()) for i in range(H)]

    max_cost = 0
    for start_y in range(H):
        for start_x in range(W):
            if S[start_y][start_x] == '#':
                continue
            costs = [[0 for w in range(W)] for h in range(H)]
            queue = Queue()
            queue.put((start_y, start_x, 1))
            cost = 1
            while not queue.empty():
                (y, x, c) = queue.get()
                if costs[y][x] != 0:
                    continue
                # print("({},{}): {}".format(y, x, c))
                costs[y][x] = c
                cost = c
                for (next_y, next_x) in [(y - 1, x), (y, x + 1), (y + 1, x), (y, x - 1)]:
                    if 0 <= next_y < H and 0 <= next_x < W and S[next_y][next_x] == '.':
                        queue.put((next_y, next_x, c + 1))
            if cost > max_cost:
                max_cost = cost
            # print("--- cost={}".format(max_cost))
            # print_costs(costs)
            # print()

    return str(max_cost - 1)


def main():
    result = solve(sys.stdin)
    if result:
        print(result)


if __name__ == '__main__':
    main()


# Optimized solution
import sys
from queue import Queue


def print_costs(costs):
    for c in costs:
        print(c)


def solve(inp):
    (H, W) = list(map(int, inp.readline().strip().split(' ')))
    S = [list(inp.readline().strip()) for i in range(H)]

    max_cost = 0
    for start_y in range(H):
        for start_x in range(W):
            if S[start_y][start_x] == '#':
                continue
            costs = [[0 for w in range(W)] for h in range(H)]
            costs[start_y][start_x] = 1
            queue = Queue()
            queue.put((start_y, start_x))
            cost = 1
            while not queue.empty():
                (y, x) = queue.get()
                # print("({},{}): {}".format(y, x, c))
                for (next_y, next_x) in [(y - 1, x), (y, x + 1), (y + 1, x), (y, x - 1)]:
                    if 0 <= next_y < H and 0 <= next_x < W and S[next_y][next_x] == '.' and costs[next_y][next_x] == 0:
                        costs[next_y][next_x] = costs[y][x] + 1
                        if cost < costs[next_y][next_x]:
                            cost = costs[next_y][next_x]
                        queue.put((next_y, next_x))
            if cost > max_cost:
                max_cost = cost
            # print("--- cost={}".format(max_cost))
            # print_costs(costs)
            # print()

    return str(max_cost - 1)


def main():
    result = solve(sys.stdin)
    if result:
        print(result)


if __name__ == '__main__':
    main()
# Original solution
import queue
import copy

def main():
    H, W = list(map(int, input().split()))
    S = []

    for i in range(H):
        S.append(list(input()))


    def bfs(start, S2):
        q = queue.Queue()
        q.put(start)
        candidates = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        dist = [[0]*W for _ in range(H)]
        while not q.empty():
            i = q.get()
            x = i[0]
            y = i[1]
            S2[x][y] = "#"

            for candi in candidates:
                x_new = x + candi[0]
                y_new = y + candi[1]

                if x_new < H and x_new >= 0:
                    if y_new < W and y_new >=0:
                        if S2[x_new][y_new] == ".":
                            dist[x_new][y_new] = dist[x][y] + 1
                            q.put([x_new, y_new])

        ans = 0
        for i in range(H):
            ans = max(ans, max(dist[i]))

        return ans

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

    print(ans)


if __name__ == "__main__":
    main()


# Optimized solution
import queue
import copy

def main():
    H, W = list(map(int, input().split()))
    S = []

    for i in range(H):
        S.append(list(input()))


    def bfs(start, S2):
        q = queue.Queue()
        q.put(start)
        candidates = [[0, 1], [1, 0], [0, -1], [-1, 0]]
        dist = [[0]*W for _ in range(H)]
        S2[start[0]][start[1]] = "#"
        while not q.empty():
            i = q.get()
            x = i[0]
            y = i[1]

            for candi in candidates:
                x_new = x + candi[0]
                y_new = y + candi[1]

                if x_new < H and x_new >= 0:
                    if y_new < W and y_new >=0:
                        if S2[x_new][y_new] == ".":
                            dist[x_new][y_new] = dist[x][y] + 1
                            S2[x_new][y_new] = "#"
                            q.put([x_new, y_new])

        ans = 0
        for i in range(H):
            ans = max(ans, max(dist[i]))

        return ans

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


    print(ans)


if __name__ == "__main__":
    main()
# Original solution
import sys
import itertools
import collections


def search(H, W, S, start, end):
    wall_i = ord(b'#')
    used = [[-1 for h in range(W)] for w in range(H)]

    qu = collections.deque()
    qu.append(start)
    used[start[0]][start[1]] = 0

    while qu:
        h, w = qu.popleft()
        cost = used[h][w]
        for h0, w0 in ((h - 1, w), (h + 1, w), (h, w - 1), (h, w + 1)):
            if not (0 <= h0 < H and 0 <= w0 < W):
                continue
            if used[h0][w0] != -1:
                continue
            if S[h0][w0] == wall_i:
                continue

            if (h0, w0) == end:
                return cost + 1
            used[h0][w0] = cost + 1
            qu.append((h0, w0))
        cost += 1

    return -1


def resolve(in_):
    H, W = list(map(int, next(in_).split()))
    S = tuple(s.strip() for s in itertools.islice(in_, H))

    road_i = ord(b'.')

    roads = []
    for h in range(H):
        for w in range(W):
            if S[h][w] == road_i:
                roads.append((h, w))
    
    ans = max(search(H, W, S, start, end) for start, end in itertools.permutations(roads, 2))
    
    return ans


def main():
    answer = resolve(sys.stdin.buffer)
    print(answer)


if __name__ == '__main__':
    main()


# Optimized solution
import sys
import itertools
import collections


def search(H, W, S, start):
    wall_i = ord(b'#')
    used = [[-1 for h in range(W)] for w in range(H)]

    qu = collections.deque()
    qu.append(start)
    used[start[0]][start[1]] = 0

    while qu:
        h, w = qu.popleft()
        cost = used[h][w]
        for h0, w0 in ((h - 1, w), (h + 1, w), (h, w - 1), (h, w + 1)):
            if not (0 <= h0 < H and 0 <= w0 < W):
                continue
            if used[h0][w0] != -1:
                continue
            if S[h0][w0] == wall_i:
                continue

            used[h0][w0] = cost + 1
            qu.append((h0, w0))

    return max(cost for costs in used for cost in costs)


def resolve(in_):
    H, W = list(map(int, next(in_).split()))
    S = tuple(s.strip() for s in itertools.islice(in_, H))

    road_i = ord(b'.')

    roads = []
    for h in range(H):
        for w in range(W):
            if S[h][w] == road_i:
                roads.append((h, w))
    
    ans = max(search(H, W, S, start) for start in roads)
    
    return ans


def main():
    answer = resolve(sys.stdin.buffer)
    print(answer)


if __name__ == '__main__':
    main()
# Original solution
from sys import stdin
import queue

H, W = [int(x) for x in stdin.readline().rstrip().split()]
maze = [stdin.readline().rstrip().split()[0] for _ in range(H)]

ans = 0

for h in range(H):
    for w in range(W):
        if maze[h][w] == '#':
            continue
        else:
            q = queue.Queue()
            q.put((h, w, 0))
            temp_h = h
            temp_w = w
            visited = [[0] * W for _ in range(H)]
            while q.qsize() > 0:
                temp = q.get()
                temp_h = temp[0]
                temp_w = temp[1]
                temp_d = temp[2]
                ans = max(ans, temp_d)
                visited[temp_h][temp_w] = 1
                if temp_h + 1 < H and maze[temp_h + 1][temp_w] == '.' and visited[temp_h + 1][temp_w] == 0:
                    q.put((temp_h + 1, temp_w, temp_d + 1))
                if temp_h - 1 >= 0 and maze[temp_h - 1][temp_w] == '.' and visited[temp_h - 1][temp_w] == 0:
                    q.put((temp_h - 1, temp_w, temp_d + 1))
                if temp_w + 1 < W and maze[temp_h][temp_w + 1] == '.' and visited[temp_h][temp_w + 1] == 0:
                    q.put((temp_h, temp_w + 1, temp_d + 1))
                if temp_w - 1 >= 0 and maze[temp_h][temp_w - 1] == '.' and visited[temp_h][temp_w - 1] == 0:
                    q.put((temp_h, temp_w - 1, temp_d + 1))

print(ans)

# Optimized solution
from sys import stdin
import queue

H, W = [int(x) for x in stdin.readline().rstrip().split()]
maze = [stdin.readline().rstrip().split()[0] for _ in range(H)]

ans = 0

for h in range(H):
    for w in range(W):
        if maze[h][w] == '#':
            continue
        else:
            q = queue.Queue()
            q.put((h, w))
            visited = [[-1] * W for _ in range(H)]
            visited[h][w] = 0
            while q.qsize() > 0:
                temp = q.get()
                temp_h = temp[0]
                temp_w = temp[1]
                ans = max(ans, visited[temp_h][temp_w])
                if temp_h + 1 < H and maze[temp_h + 1][temp_w] == '.' and visited[temp_h + 1][temp_w] < 0:
                    visited[temp_h + 1][temp_w] = visited[temp_h][temp_w] + 1
                    q.put((temp_h + 1, temp_w))
                if temp_h - 1 >= 0 and maze[temp_h - 1][temp_w] == '.' and visited[temp_h - 1][temp_w] < 0:
                    visited[temp_h - 1][temp_w] = visited[temp_h][temp_w] + 1
                    q.put((temp_h - 1, temp_w))
                if temp_w + 1 < W and maze[temp_h][temp_w + 1] == '.' and visited[temp_h][temp_w + 1] < 0:
                    visited[temp_h][temp_w + 1] = visited[temp_h][temp_w] + 1
                    q.put((temp_h, temp_w + 1))
                if temp_w - 1 >= 0 and maze[temp_h][temp_w - 1] == '.' and visited[temp_h][temp_w - 1] < 0:
                    visited[temp_h][temp_w - 1] = visited[temp_h][temp_w] + 1
                    q.put((temp_h, temp_w - 1))

print(ans)
# Original solution
from queue import Queue

h, w = list(map(int, input().split()))
s = []
for i in range(h):
    s.append(input().strip())

ans = 0
for i in range(h):
    for j in range(w):
        start = s[i][j]
        if start == "#":
            continue
        else:
            visited = [[False for k in range(w)] for l in range(h)]
            queue = Queue()
            queue.put((i, j, 0))

            while 0 < queue.qsize():
                now = queue.get()
                visited[now[0]][now[1]] = True
                ans = max(ans, now[2])

                if (now[0] <= (h - 2)):
                    if (s[now[0] + 1][now[1]] == ".") and not visited[now[0] + 1][now[1]]:
                        queue.put(((now[0] + 1), now[1], (now[2] + 1)))
                if (now[1] <= (w - 2)):
                    if (s[now[0]][now[1] + 1] == ".") and not visited[now[0]][now[1] + 1]:
                        queue.put((now[0], (now[1] + 1), (now[2] + 1)))
                if (1 <= now[0]):
                    if (s[now[0] - 1][now[1]] == ".") and not visited[now[0] - 1][now[1]]:
                        queue.put(((now[0] - 1), now[1], (now[2] + 1)))
                if (1 <= now[1]):
                    if (s[now[0]][now[1] - 1] == ".") and not visited[now[0]][now[1] - 1]:
                        queue.put((now[0], (now[1] - 1), (now[2] + 1)))

print(ans)


# Optimized solution
from queue import Queue

h, w = list(map(int, input().split()))
s = []
for i in range(h):
    s.append(input().strip())

ans = 0
for i in range(h):
    for j in range(w):
        start = s[i][j]
        if start == "#":
            continue
        else:
            visited = [[False for _ in range(w)] for _ in range(h)]
            visited[i][j] = True
            queue = Queue()
            queue.put((i, j, 0))

            while 0 < queue.qsize():
                now = queue.get()
                ans = max(ans, now[2])

                if (now[0] <= (h - 2)) and (s[now[0] + 1][now[1]] == ".") and not visited[now[0] + 1][now[1]]:
                    queue.put(((now[0] + 1), now[1], (now[2] + 1)))
                    visited[now[0] + 1][now[1]] = True
                if (now[1] <= (w - 2)) and (s[now[0]][now[1] + 1] == ".") and not visited[now[0]][now[1] + 1]:
                    queue.put((now[0], (now[1] + 1), (now[2] + 1)))
                    visited[now[0]][now[1] + 1] = True
                if (1 <= now[0]) and (s[now[0] - 1][now[1]] == ".") and not visited[now[0] - 1][now[1]]:
                    queue.put(((now[0] - 1), now[1], (now[2] + 1)))
                    visited[now[0] - 1][now[1]] = True
                if (1 <= now[1]) and (s[now[0]][now[1] - 1] == ".") and not visited[now[0]][now[1] - 1]:
                    queue.put((now[0], (now[1] - 1), (now[2] + 1)))
                    visited[now[0]][now[1] - 1] = True

print(ans)