package main

import (
	"fmt"
)

type point struct {
	y, x int
}
type queue []point

func (q *queue) push(p point) {
	*q = append(*q, p)
}

func (q *queue) pop() {
	if len(*q) == 0 {
		return
	}
	*q = (*q)[1:]
}

var h, w int
var move = []point{{-1, 0}, {0, 1}, {1, 0}, {0, -1}}

func main() {
	fmt.Scan(&h)
	fmt.Scan(&w)

	field := make([]string, h, w)
	for i := 0; i < h; i++ {
		fmt.Scan(&field[i])
	}

	var ans int
	dist := make([][]int, h)

	for i := 0; i < h; i++ {
		for j := 0; j < w; j++ {
			//			if string(field[i][j]) == "#" {
			//				continue
			//			}
			//
			//			for di, _ := range dist {
			//				dist[di] = make([]int, w)
			//				for dj, _ := range dist[di] {
			//					dist[di][dj] = -1
			//				}
			//			}
			//
			//			q := queue{}
			//			q.push(point{i, j})
			//
			//			var update = func(y, x, v int) {
			//				if dist[y][x] != -1 {
			//					return
			//				}
			//				dist[y][x] = v
			//				q.push(point{y, x})
			//			}
			//			update(i, j, 0)
			//
			//			for len(q) > 0 {
			//				x := q[0].x
			//				y := q[0].y
			//				q.pop()
			//
			//				for _, m := range move {
			//					nx := x + m.x
			//					ny := y + m.y
			//					if nx < 0 || nx >= w || ny < 0 || ny >= h {
			//						continue
			//					}
			//					if string(field[ny][nx]) == "#" {
			//						continue
			//					}
			//					update(ny, nx, dist[y][x]+1)
			//				}
			//			}
			//
			//			for di, _ := range dist {
			//				for _, v := range dist[di] {
			//					if ans < v {
			//						ans = v
			//					}
			//				}
			//			}
		}
	}
	fmt.Print(ans)
}
