Harryxun/sft_time huggingface dataset:
### BUGGY CODE ###

H, W, M = map(int, input().split())
Hsum = [0] * H
Wsum = [0] * W

hw = []
for m in range(M):
  h, w = map(int, input().split())
  Hsum[h-1] += 1
  Wsum[w-1] += 1
  hw.append(str(h)+"_"+str(w))

res = []
for h in range(H):
  for w in range(W):
    if str(h+1)+"_"+str(w+1) in hw:
      res.append(Hsum[h]+Wsum[w]-1)
    else:
      res.append(Hsum[h]+Wsum[w])

print(max(res))

### FIXED CODE ###

import sys
input = sys.stdin.readline
 
H, W, M = map(int, input().split())
Hsum = [0] * H
Wsum = [0] * W
hw = set()
for m in range(M):
  h, w = map(lambda x: int(x) - 1, input().split())
  Hsum[h] += 1
  Wsum[w] += 1
  hw.add((h, w))

mh = max(Hsum)
mw = max(Wsum)
hidx = [i for i, _ in enumerate(Hsum) if _ == mh]
widx = [i for i, _ in enumerate(Wsum) if _ == mw]
 
if len(hidx) * len(widx) > M:
  print(mh + mw)
else:
  fi_flg = False
  for h in hidx:
    for w in widx:
      if (h, w) not in hw:
        print(mh + mw)
        fi_flg = True
        break
    if fi_flg:
      break
  if fi_flg is False:
    print(mh + mw - 1)
### BUGGY CODE ###

# coding: utf-8
N, Q = map(int, input().split())
S = input()
l = [0] * N
for i in range(N - 1):
    if S[i] == 'A' and S[i + 1] == 'C':
        l[i] = 1
        l[i + 1] = -1
for _ in range(Q):
    ans = 0
    a, b = map(int, input().split())
    for i in range(a - 1, b - 1):
        if l[i] == 1 and l[i + 1] == -1:
            ans += 1
    print(ans)

### FIXED CODE ###

# coding: utf-8
N, Q = map(int, input().split())
S = input()
c = 0
lst = [0] * N
for i in range(N - 1):
    if S[i] == 'A' and S[i + 1] == 'C':
        c += 1
    lst[i + 1] = c
for _ in range(Q):
    a, b = map(int, input().split())
    print(lst[b - 1] - lst[a - 1])
### BUGGY CODE ###

import fractions
import sys
input = sys.stdin.readline


N = int(input())
A = tuple(map(int, input().split()))


def modinv(a, mod=10**9+7):
    return pow(a, mod-2, mod)


mod = 10**9+7
lcm = 1
B = [0]*N

for i in range(N):
    lcm = (lcm // fractions.gcd(lcm, A[i])) * A[i]

ans = 0

for i in range(N):
    ans += (lcm * modinv(A[i]))
    ans %= mod

print(ans)


### FIXED CODE ###

import fractions
import sys
input = sys.stdin.readline


P = 10**9 + 7
N = (10**6)+1
inv_t = [0]+[1]
for i in range(2, N):
    inv_t += [inv_t[P % i] * (P - int(P / i)) % P]

N = int(input())
A = tuple(map(int, input().split()))

mod = 10**9+7
lcm = 1
B = [0]*N

for i in range(N):
    lcm = (lcm // fractions.gcd(lcm, A[i])) * A[i]

ans = 0

lcm %= mod
for i in range(N):
    ans += (lcm * inv_t[A[i]]) % mod
    ans %= mod

print(ans)
### BUGGY CODE ###

s = input()

mod = 10**9+7
n = len(s)
dp = [[0]*13 for _ in range(n+1)]
dp[0][0] = 1
for i in range(n):
    if s[i] == '?':
        for j in range(10):
            for k in range(13):
                dp[i+1][(k*10+j)%13] += dp[i][k]
    else:
        for k in range(13):
            dp[i+1][(k*10+int(s[i]))%13] += dp[i][k]
    for k in range(13):
        dp[i+1][k] %= mod
print(dp[n][5])


### FIXED CODE ###

s = input()

mod = 10**9+7
n = len(s)
dp = [[0]*13 for _ in range(n+1)]
dp[0][0] = 1
for i in range(n):
    if s[i] == '?':
        for j in range(10):
            for k in range(13):
                dp[i+1][(k*10+j)%13] += dp[i][k]
    else:
        for k in range(13):
            dp[i+1][(k*10+int(s[i]))%13] += dp[i][k]
    for k in range(13):
        dp[i+1][k] %= mod
print(dp[n][5])
### BUGGY CODE ###

n = int(input())
p = list(map(int,input().split()))
c = 0
for i in range(1,n+1):
  if p[i-1] == min(p[:i]):
    c += 1
print(c)

### FIXED CODE ###

n = int(input())
p = list(map(int,input().split()))
c = 0
m = p[0]
for i in range(n):
    if p[i] <= m :
        m = p[i]
        c += 1
print(c)
### BUGGY CODE ###

N, M = map(int, input().split())
a_list = list(map(int, input().split()))

items = {
    1: 2, 2: 5, 3: 5, 4: 4, 5: 5, 6: 6, 7: 3, 8: 7, 9: 6
}
dp = [0] * (N + 1)

b_list = []
for a in a_list:
    need = items[a]
    if need <= N:
        dp[need] = a
        b_list.append(a)

M = len(b_list)
b_list.sort()
for i in range(N + 1):
    for b in b_list:
        if i - items[b] >= 0:
            if dp[i - items[b]] != 0:
                cnt = 0
                num = dp[i - items[b]]
                while num != 0:
                    cnt += 1
                    num //= 10
                tmp = max(b * (10 ** cnt) + dp[i - items[b]], dp[i - items[b]] * 10 + b)
                dp[i] = max(tmp, dp[i])
print(dp[N])


### FIXED CODE ###

N, M = map(int, input().split())
a_list = list(map(int, input().split()))

items = {
    1: 2, 2: 5, 3: 5, 4: 4, 5: 5, 6: 6, 7: 3, 8: 7, 9: 6
}

dp = [-float("inf")] * (N + 1)
b_list = []
for a in a_list:
    need = items[a]
    if need <= N:
        dp[need] = 1
        b_list.append(a)

M = len(b_list)
dp[0] = 0
for i in range(N + 1):
    for b in b_list:
        if i - items[b] >= 0:
            if dp[i - items[b]] != -float("inf"):
                dp[i] = max(dp[i], dp[i - items[b]] + 1)

b_list.sort(reverse=True)
ans = ""

for i in range(dp[N]):
    for b in b_list:
        if dp[N - items[b]] == dp[N] - 1:
            ans += str(b)
            N -= items[b]
            break
print(ans)
### BUGGY CODE ###

n,m=map(int,input().split())
x=list(map(int,input().split()))
n = min(n,len(x))

xs=sorted(x)
# xs

def sabun(x,i):
    return x[i+1]-x[i]

sabunx=[sabun(xs,i) for i in range(m-1)]
# sabunx

for _ in range(n-1):
    sabunx.remove(sabunx[sabunx.index(sorted(sabunx,reverse=True)[0])])
#     print(sabunx)
    
print(sum(sabunx))

### FIXED CODE ###

import numpy as np

n,m=map(int,input().split())
x=list(map(int,input().split()))
n = min(n,len(x))

xs=sorted(x)
# xs

# def sabun(x,i):
#     return x[i+1]-x[i]

def sabun(x):
    a=np.array(x)
    return list(a[1:]-a[:-1])

# sabunx=[sabun(xs,i) for i in range(m-1)]

sabunx=sabun(xs)
# sabunx

print(sum(sorted(sabunx,reverse=True)[n-1:]))
### BUGGY CODE ###

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

M = [[[0, 0] for i in range(W)] for j in range(H)]
V = [[[False, False] for i in range(W)] for j in range(H)]


def search(grid, h, w, H, W, V_lst):
    h_cnt = 0
    v_cnt = 0

    if w != W and not V_lst[1]:
        for _ in range(W):
            if grid[h][w + h_cnt] != '#':
                h_cnt += 1
                if w + h_cnt == W:
                    break

    if h != H and not V_lst[0]:
        for _ in range(H):
            if grid[h + v_cnt][w] != '#':
                v_cnt += 1
                if h + v_cnt == H:
                    break

    return h_cnt, v_cnt

for h in range(H):
    for w in range(W):
        if grid[h][w] == '#':
            continue
        else:
            h_cnt, v_cnt = search(grid, h, w, H, W, V[h][w])

            for i in range(h_cnt):
                V[h][w + i][1] = True
                M[h][w + i][1] = h_cnt - 1

            for i in range(v_cnt):
                V[h + i][w][0] = True
                M[h + i][w][0] = v_cnt - 1

m = -1
for h in range(H):
    for w in range(W):
        if M[h][w][0] + M[h][w][1] > m:
            m = M[h][w][0] + M[h][w][1] + 1

print(m)

### FIXED CODE ###

H, W = map(int, input().split())

grid = []

for i in range(H):
    s = input()
    r = []
    for j, x in enumerate(s):
        r.append(x)

    grid.append(r)


H_cnt = [[0] * W for _ in range(H)]
W_cnt = [[0] * W for _ in range(H)]

for r in range(H):
    idx = 0

    while idx < W:
        if grid[r][idx] == '.' and (idx == 0 or grid[r][idx - 1] == '#'):
            cnt = 1
            st = idx
            if idx == W - 1 or grid[r][idx + 1] == '#':
                W_cnt[r][idx] = 1
        elif grid[r][idx] == '.' and (idx == W - 1 or grid[r][idx + 1] == '#'):
            cnt += 1
            for i in range(st, idx + 1):
                W_cnt[r][i] = cnt
        elif grid[r][idx] == '.':
            cnt += 1
        elif grid[r][idx] == '#':
            pass

        idx += 1

for c in range(W):
    idx = 0

    while idx < H:
        if grid[idx][c] == '.' and (idx == 0 or grid[idx - 1][c] == '#'):
            cnt = 1
            st = idx
            if idx == H - 1 or grid[idx + 1][c] == '#':
                H_cnt[idx][c] = 1
        elif grid[idx][c] == '.' and (idx == H - 1 or grid[idx + 1][c] == '#'):
            cnt += 1
            for i in range(st, idx + 1):
                H_cnt[i][c] = cnt
        elif grid[idx][c] == '.':
            cnt += 1
        elif grid[idx][c] == '#':
            pass

        idx += 1

max_ = 0
for r in range(H):
    for c in range(W):
        max_ = max(max_, W_cnt[r][c] + H_cnt[r][c] - 1)

print(max_)
### BUGGY CODE ###

import sys
input = sys.stdin.readline
import scipy as sp

N = int(input())
S = input()
Q = int(input())
*K, = map(int,input().split())

D,M,C = [],[],[]
for i,s in enumerate(S):
    if s=="D":
        D.append(i+1)
    elif s=="M":
        M.append(i+1)
    elif s=="C":
        C.append(i+1)
if len(D)<len(C):
    D,C = [N+1-c for c in C],[N+1-d for d in D]
    M = [N+1-m for m in M]

cs = sp.cumsum
ans = sp.zeros(Q,sp.int64)
cntD = sp.zeros(N+1,sp.int64)
cntM = sp.zeros(N+1,sp.int64)
sumM = sp.zeros(N+1,sp.int64)
for i in D:
    cntD[i] = 1
cntD = cs(cntD)
for i in M:
    cntM[i] = 1
    sumM[i] = cntD[i]
cntM = cs(cntM)
sumM = cs(sumM)

for i in C:
    i -= 1
    sMi = sumM[i]
    cMi = cntM[i]
    for j,k in enumerate(K):
        ik = max(0,i-k+1)
        ans[j] += (sMi-sumM[ik]) - cntD[ik]*(cMi-cntM[ik])
for out in ans:
    print(out)


### FIXED CODE ###

N = int(input())
S = input()
Q = int(input())
*K, = map(int,input().split())

nD = S.count("D")
nC = S.count("C")
if nD < nC:
    S = S[::-1].replace("D","c").replace("C","d").upper()

D = [0]*(N+1)
cntM = [0]*(N+1)
sumM = [0]*(N+1)
ans = [0]*Q
for i,s in enumerate(S):
    D[i+1] = D[i]
    cntM[i+1] = cntM[i]
    sumM[i+1] = sumM[i]
    if s=="D":
        D[i+1] += 1
    elif s=="M":
        cntM[i+1] += 1
        sumM[i+1] += D[i]
    elif s=="C":
        for j,k in enumerate(K):
            ik = max(0,i-k+1)
            d = D[ik]
            ans[j] += (sumM[i]-sumM[ik]) - d*(cntM[i]-cntM[ik])
for out in ans:
    print(out)
### BUGGY CODE ###

n = int(input())
z = []
pre = 0
for _ in range(n):
    i = int(input())
    if i != pre:
        z.append(i)
    pre = i
n = len(z)
dp = [1] * (n+1)
place = [set() for _ in range(2 * 10 ** 5)]
for i in range(n):
    dp[i+1] = dp[i]
    for p in place[z[i] - 1]:
        dp[i+1] += dp[p]
    place[z[i] - 1].add(i)
    dp[i+1] %= 10 ** 9 + 7
print(dp[n])

### FIXED CODE ###

n = int(input())
z = []
pre = 0
for _ in range(n):
    i = int(input())
    if i != pre:
        z.append(i)
    pre = i
n = len(z)
dp = [1] * (n+1)
dpp = [0] * 2 * 10 ** 5
for i in range(n):
    dp[i+1] = dp[i] + dpp[z[i]-1]
    dpp[z[i]-1] += dp[i]
    dp[i+1] %= 10 ** 9 + 7
print(dp[n])
### BUGGY CODE ###

#!/usr/bin/env python3
import sys
from collections import Counter
from itertools import accumulate
from collections import defaultdict
INF = float("inf")


def solve(N: int, A: "List[int]"):
    c = Counter(A)

    # S = [0]*(N+1)
    # for i in range(1, N+1):
    #     for j in range(N+1):
    #         S[i] += min(c[j], i)
    # print(c)
    # print("目標: ", S)
    d = Counter(c.values())
    d = list(accumulate([d[i] for i in range(N, -1, -1)]))[::-1]
    # print(d)
    S = [0]*(N+1)
    for i in range(1, N+1):
        S[i] = S[i-1] + d[i]

    def isOK(y):
        # print("y: {}, S[{}]: {}, K*y: {}".format(y, y, S[y], K*y))
        return S[y] < K*y

    def binary_search(x):
        ng = -1
        ok = len(x)+1

        while abs(ok - ng) > 1:
            mid = (ok + ng)//2
            if isOK(mid):
                ok = mid
            else:
                ng = mid
        return ng, ok

    for K in range(1, N+1):
        # print("---{}---".format(K))
        ng, ok = binary_search(range(N))
        print(ng)

    return


def main():

    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A)


if __name__ == '__main__':
    main()


### FIXED CODE ###

#!/usr/bin/env python3
import sys
from collections import Counter
from itertools import accumulate
from collections import defaultdict
INF = float("inf")


def solve(N: int, A: "List[int]"):
    c = Counter(A)
    d = Counter(c.values())
    d = tuple(accumulate([d[i] for i in range(N, -1, -1)]))[::-1]
    S = [0]*(N+1)
    for i in range(1, N+1):
        S[i] = S[i-1] + d[i]

    def isOK(y):
        return S[y] < K*y

    def binary_search(x):
        ng = -1
        ok = len(x)+1

        while abs(ok - ng) > 1:
            mid = (ok + ng)//2
            if isOK(mid):
                ok = mid
            else:
                ng = mid
        return ng, ok

    for K in range(1, N+1):
        ng, ok = binary_search(range(N))
        print(ng)

    return


def main():

    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    A = [int(next(tokens)) for _ in range(N)]  # type: "List[int]"
    solve(N, A)


if __name__ == '__main__':
    main()
### BUGGY CODE ###

n,m=map(int,input().split())
a=list(map(int,input().split()))
for i in range(m):
    b,c=map(int,input().split())
    a+=[c]*b
    a.sort()
    a=a[b:]
print(sum(a))

### FIXED CODE ###

n,m=map(int,input().split())
*a,=map(int,input().split())
l=[list(map(int,input().split()))[::-1] for _ in range(m)]
a.sort()
d=[]
e=0
for c,b in sorted(l)[::-1]:
	d+=[c]*b
	e+=b
	if e>n:break
for i,(x,y) in enumerate(zip(a,d)):
	if x<y:a[i]=y
print(sum(a))
### BUGGY CODE ###

#約数全列挙
def make_divisors(n):
	divisors = []
	for i in range(1, int(n**0.5)+1):
		if n % i == 0:
			divisors.append(i)
			if i != n // i:
				divisors.append(n//i)
	return divisors


n=int(input())
#n%k!=0
cnt=len(make_divisors(n-1))

#n%k==0
lst=make_divisors(n)
for k in lst:
	t=n
	while t%k==0:
		t//=k
	t%=k
	if  t==1:
		cnt+=1
print(cnt-1)

### FIXED CODE ###

#約数全列挙
def make_divisors(n):
	divisors = []
	for i in range(1, int(n**0.5)+1):
		if n % i == 0:
			divisors.append(i)
			if i != n // i:
				divisors.append(n//i)
	return divisors


n=int(input())
#n%k!=0
cnt=len(make_divisors(n-1))-1

#n%k==0
lst=make_divisors(n)
for k in lst:
	if k!=1:
		t=n
		while t%k==0:
			t//=k
		if (t-1)%k==0:
			cnt+=1
print(cnt)
### BUGGY CODE ###

from collections import deque
import sys
sys.setrecursionlimit(10**7)

N=int(input())
M=N*(N-1)//2
D=[[]for i in range(M)]
F=[[]for i in range(M)]
for i in range(N):
  x=list(map(int,input().split()))
  for j in range(N-2):
    a,b,c=i+1,x[j],x[j+1]
    x1,x2=min(i+1,x[j]),max(i+1,x[j])
    y1,y2=min(i+1,x[j+1]),max(i+1,x[j+1])
    e=M-(N-x1)*(N-x1+1)//2
    f=e+(x2-x1-1)
    g=M-(N-y1)*(N-y1+1)//2
    h=g+(y2-y1-1)
    D[f].append(h)
    F[h].append(f)
    
q=deque()
P=[0]*M
for i in range(M):
  if len(F[i])==0:
    q.append((i,0))

r=[]
while q:
  v1,cnt=q.popleft()
  r.append((v1,cnt))
  for v2 in D[v1]:
    P[v2]+=1
    if P[v2]==len(F[v2]):
      q.append((v2,cnt+1))

if len(r)!=M:
  print(-1)
else:
  print(r[-1][-1]+1)

### FIXED CODE ###

from collections import deque
import sys
sys.setrecursionlimit(10**7)

N=int(input())
M=N*(N-1)//2
D=[[]for i in range(M)]
F=[[]for i in range(M)]
for i in range(N):
  x=list(map(int,input().split()))
  for j in range(N-2):
    a,b,c=i+1,x[j],x[j+1]
    x1,x2=min(i+1,x[j]),max(i+1,x[j])
    y1,y2=min(i+1,x[j+1]),max(i+1,x[j+1])
    e=M-(N-x1)*(N-x1+1)//2
    f=e+(x2-x1-1)
    g=M-(N-y1)*(N-y1+1)//2
    h=g+(y2-y1-1)
    D[f].append(h)
    F[h].append(f)
    
q=deque()
P=[0]*M
for i in range(M):
  if len(F[i])==0:
    q.append((i,0))

r=[]
while q:
  v1,cnt=q.popleft()
  r.append((v1,cnt))
  for v2 in D[v1]:
    P[v2]+=1
    if P[v2]==len(F[v2]):
      q.append((v2,cnt+1))

if len(r)!=M:
  print(-1)
else:
  print(r[-1][-1]+1)
### BUGGY CODE ###

import numpy as np

N, M = map(int, input().split())
a = np.array([int(input()) for _ in range(M)])

step0 = 1
step1 = 0 if (1 in a) else 1

ans = [step0, step1]
for i in range(2, N+1):
    ans.append(0 if i in a else ans[-1] + ans[-2])
print(ans[-1] % 1000000007)

### FIXED CODE ###

import numpy as np

N, M = map(int, input().split())
A = [1]*(N+1)
for _ in range(M):
    A[int(input())] = 0

step0 = 1
step1 = A[1]

ans = [step0, step1]
for i in range(2, N+1):
    now = (ans[-1] + ans[-2]) * A[i]
    ans.append(now)
print(ans[-1] % 1000000007)
### BUGGY CODE ###

# -*- coding: utf-8 -*-

import sys
import itertools
import math

def main():
    N, M = map(int, input().split())
    S = input()
    T = input()

    if N < M:
        t = M
        M = N
        N = t
        q = S
        S = T
        T = q

    ret = -1
    for step in range(1, M+1):
        slen = step * N
        if slen % M != 0:
            continue
        mstep = slen // M
        good = True
        for i in range(N):
            u = (step * i) % mstep
            if u != 0:
                continue
            j = (step * i) // mstep
            if S[i] != T[j]:
                good = False
                break
        if good:
            ret = step * N
            break

    # 出力
    print("{}".format(ret))


if __name__ == '__main__':
    main()



### FIXED CODE ###

# -*- coding: utf-8 -*-

import sys
import itertools
import math

def gcd(a, b):
    if a < b:
        a, b = b, a
    if b == 0:
        return a
    c = a % b
    return gcd(b, c)

def main():
    N, M = map(int, input().split())
    S = input()
    T = input()

    if N < M:
        t = M
        M = N
        N = t
        q = S
        S = T
        T = q

    d = gcd(N,M)
    c = N * M // d

    ret = -1
    slen = c
    nstep = slen // N
    mstep = slen // M

    dd = gcd(nstep, mstep)
    cc = nstep * mstep // dd

    good = True
    for k in range(0, slen, cc):
        u = (k // nstep) % N
        j = (k // mstep) % M
        if S[u] != T[j]:
            good = False
            break
    if good:
        ret = slen

    # 出力
    print("{}".format(ret))


if __name__ == '__main__':
    main()
### BUGGY CODE ###

import math
from functools import reduce

def gcd(*numbers):
    return reduce(math.gcd, numbers)

def gcd_list(numbers):
    return reduce(math.gcd, numbers)

def make_divisors(n):
    lower_divisors , upper_divisors = [], []
    i = 1
    while i*i <= n:
        if n % i == 0:
            if i != 1:
                lower_divisors.append(i)
            if i != n // i:
                upper_divisors.append(n//i)
        i += 1
    return lower_divisors + upper_divisors[::-1]

n = int(input())
a = list(map(int,input().split()))

# pairwise coprime -> それぞれがすべて互いに素
# setwise coprime -> 互いに素でないのは混じっているが全体のgcdは1

b = [[]]*n
for i in range(n):
    b[i] = make_divisors(a[i])
# print(b)


if gcd_list(a) != 1:
    print("not coprime")
    exit()

p = {1}
for i in range(n):
    l1 = len(p)
    p = p.union(set(b[i]))
    l2 = len(p)
    # print(l1,l2)
    if l1 + len(b[i]) != l2:
        print("setwise coprime")
        exit()

print("pairwise coprime")

### FIXED CODE ###

import math
from functools import reduce

def gcd(*numbers):
    return reduce(math.gcd, numbers)

def gcd_list(numbers):
    return reduce(math.gcd, numbers)

import itertools
import collections

def prime_factor_table(n):
    table = [0] * (n + 1)
    
    for i in range(2, n + 1):
        if table[i] == 0:
            for j in range(i + i, n + 1, i):
                table[j] = i
    
    return table

def prime_factor(n, prime_factor_table):
    prime_count = collections.Counter()
    
    while prime_factor_table[n] != 0:
        prime_count[prime_factor_table[n]] += 1
        n //= prime_factor_table[n]
    prime_count[n] += 1
    
    return prime_count

n = int(input())
a = list(map(int,input().split()))

# pairwise coprime -> それぞれがすべて互いに素
# setwise coprime -> 互いに素でないのは混じっているが全体のgcdは1

if gcd_list(a) != 1:
    print("not coprime")
    exit()

pft = prime_factor_table(10**6)
pf = [0]*(10**6+1)

for i in a:
    if i == 1:
        continue
    # print(prime_factor(i, pft).keys())
    for j in prime_factor(i, pft).keys():
        if pf[j] == 1:
            print("setwise coprime")
            exit()
        pf[j] += 1

print("pairwise coprime")
### BUGGY CODE ###

n,m=map(int,input().split())
a=[]
for i in range(m):
    x,y,z=map(int,input().split())
    a.append((x-1,y-1,z))

class union:
    def __init__(self,num):
        self.par=[-1]*num
    def get_par(self,node):
        if self.par[node]==-1:
            return node
        else:
            return self.get_par(self.par[node])
    def merge(self,x,y):
        X=self.get_par(x)
        Y=self.get_par(y)
        if X!=Y:
            self.par[Y]=X
    def output(self):
        print(self.par)
    def count(self):
        print(self.par.count(-1))
u=union(n)
for i in range(m):
    u.merge(a[i][0],a[i][1])
u.count()

### FIXED CODE ###

n,m=map(int,input().split())
a=[]
for i in range(m):
    x,y,z=map(int,input().split())
    a.append((x-1,y-1))

class union:
    def __init__(self,num):
        self.par=[-1]*num
    def get_par(self,node):
        if self.par[node]==-1:
            return node
        else:
            x=self.get_par(self.par[node])
            return x
    def merge(self,x,y):
        X=self.get_par(x)
        Y=self.get_par(y)
        if X!=Y:
            self.par[Y]=X
    def output(self):
        print(self.par)
    def count(self):
        print(self.par.count(-1))
def get_parent(node):
    if par[node]==-1:
        return node
    else:
        par[node]=get_parent(par[node])
        return par[node]
    
def merge(x,y):
    i=get_parent(x)
    j=get_parent(y)
    if i!=j:
        par[i]=j
    return
par=[-1]*n
for i in range(m):
    merge(a[i][0],a[i][1])
print(par.count(-1))
### BUGGY CODE ###

from collections import deque

INF = 10000

H, W = map(int, input().split())
Sss = ['#'*(W+2)] + ['#'+input()+'#' for _ in range(H)] + ['#'*(W+2)]

poss = []
for i in range(1, H+1):
    for j in range(1, W+1):
        if Sss[i][j] == '.':
            poss.append((i, j))

def bfsGridGraph(Sss, xSt, ySt, xEn, yEn, INF):
    dxys = [(-1,0), (1,0), (0,-1), (0,1)]
    distss = [[(INF if S != '#' else -1) for S in Ss] for Ss in Sss]
    distss[xSt][ySt] = 0
    Q = deque([(xSt, ySt)])
    while Q:
        x, y = Q.popleft()
        dist = distss[x][y]
        for dx, dy in dxys:
            x2, y2 = x+dx, y+dy
            if distss[x2][y2] == INF:
                distss[x2][y2] = dist + 1
                Q.append((x2, y2))
    return distss

N = len(poss)
ans = 0
for i in range(N):
    xSt, ySt = poss[i]
    for j in range(i+1, N):
        xEn, yEn = poss[j]
        distss = bfsGridGraph(Sss, xSt, ySt, xEn, yEn, INF)
        dist = distss[xEn][yEn]
        ans = max(ans, dist)

print(ans)


### FIXED CODE ###

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

H, W = map(int, input().split())
Sss = ['#'*(W+2)] + ['#'+input()+'#' for _ in range(H)] + ['#'*(W+2)]

N = H*W
adjL = [[] for _ in range(N)]
for x in range(1, H+1):
    for y in range(1, W+1):
        if Sss[x][y] != '.': continue
        for dx, dy in dxys:
            x2, y2 = x+dx, y+dy
            if Sss[x2][y2] != '.': continue
            z = (x-1)*W + y-1
            z2 = (x2-1)*W + y2-1
            adjL[z].append(z2)

# 重みなしグラフの直径を求める
def getDiameterOfUnweightedGraph(adjList):
    numV = len(adjList)
    def bfs(vSt):
        costs = [-1] * numV
        costs[vSt] = cost = 0
        vs = [vSt]
        while vs:
            cost += 1
            v2s = []
            for v in vs:
                for v2 in adjList[v]:
                    if costs[v2] == -1:
                        costs[v2] = cost
                        v2s.append(v2)
            vs = v2s
        return cost - 1
    return max([bfs(vSt) for vSt in range(numV)])

maxDist = getDiameterOfUnweightedGraph(adjL)
print(maxDist)