# まず、xの値でソート（同値の場合はyでソート）する。
# この状態で、全ての2点について、x,yの差を求める
# 差の情報(p,q)の回数が最も大きいものが答えの候補
# (p,q)で到達できる点にはコスト0で行けるグラフの最短距離を解く

N=int(input())
ball=[None] * N
for i in range(N):
  ball[i] = list(map(int,input().split()))

ball=sorted(ball,key=lambda x:(x[0],x[1]))

from collections import defaultdict
dic = defaultdict(list)

for i in range(N-1):
  for j in range(i+1,N):
    # 点iから点jへは(p,q)で到達できる
    dic[(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append((i,j))

pq=None
target=[]
for item in dic.items():
  if len(item[1]) > len(target):
    target = item[1]
    pq=item[0]
    
# targetの要素で、同じ点を持つものは結合して1つの点にできる。
# UnionFind

# 0-indexed
class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size)

UF=UnionFind(N)
for i,j in target:
  UF.unite(i,j)
  
print(len(UF.get_roots())) N=int(input()) N int(input()) int input() input ball=[None] * N ball [None] * N [None] None N for i in range(N):
  ball[i] = list(map(int,input().split())) i range(N) range N ball[i] = list(map(int,input().split())) ball[i] ball i list(map(int,input().split())) list map(int,input().split()) map int input().split() ().split () input split ball=sorted(ball,key=lambda x:(x[0],x[1])) ball sorted(ball,key=lambda x:(x[0],x[1])) sorted ball key=lambda x:(x[0],x[1]) key lambda x:(x[0],x[1]) (x[0],x[1]) x[0] x 0 x[1] x 1 x from collections import defaultdict dic = defaultdict(list) dic defaultdict(list) defaultdict list for i in range(N-1):
  for j in range(i+1,N):
    # 点iから点jへは(p,q)で到達できる
    dic[(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append((i,j)) i range(N-1) range N-1 N 1 for j in range(i+1,N):
    # 点iから点jへは(p,q)で到達できる
    dic[(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append((i,j)) j range(i+1,N) range i+1 i 1 N dic[(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append((i,j)) [(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append [(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])] dic (ball[j][0] - ball[i][0],ball[j][1] - ball[i][1]) ball[j][0] - ball[i][0] ball[j][0] [j] ball j 0 ball[i][0] [i] ball i 0 ball[j][1] - ball[i][1] ball[j][1] [j] ball j 1 ball[i][1] [i] ball i 1 append (i,j) i j pq=None pq None target=[] target [] for item in dic.items():
  if len(item[1]) > len(target):
    target = item[1]
    pq=item[0]
    
# targetの要素で、同じ点を持つものは結合して1つの点にできる。
# UnionFind

# 0-indexed item dic.items() dic.items dic items if len(item[1]) > len(target):
    target = item[1]
    pq=item[0]
    
# targetの要素で、同じ点を持つものは結合して1つの点にできる。
# UnionFind

# 0-indexed len(item[1]) > len(target) len(item[1]) len item[1] item 1 len(target) len target target = item[1] target item[1] item 1 pq=item[0] pq item[0] item 0 class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size) UnionFind N=0 N 0 parent=None parent None size=None size None def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
   __init__ self.N=N self.N self N N i for i in range(self.N) for i in range(self.N) i range(self.N) range self.N self N for i in range(self.N) i self.parent=[i for i in range(self.N)] self.parent self parent [i for i in range(self.N)] self.size=[1]*self.N self.size self size [1]*self.N [1] 1 self.N self N self self N N def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
   root while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
     x!=self.parent[x] x self.parent[x] self.parent self parent x self.parent[x]=self.parent[self.parent[x]] self.parent[x] self.parent self parent x self.parent[self.parent[x]] self.parent self parent self.parent[x] self.parent self parent x x=self.parent[x] x self.parent[x] self.parent self parent x return x x self self x x def same(self,x,y):
    return self.root(x)==self.root(y)
  
   same return self.root(x)==self.root(y) self.root(x)==self.root(y) self.root(x) self.root self root x self.root(y) self.root self root y self self x x y y def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
   unite x=self.root(x) x self.root(x) self.root self root x y=self.root(y) y self.root(y) self.root self root y if x==y:
      return
     x==y x y return if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
   self.size[x]>self.size[y] self.size[x] self.size self size x self.size[y] self.size self size y self.parent[y]=x self.parent[y] self.parent self parent y x self.size[x]+=self.size[y] self.size[x] self.size self size x self.size[y] self.size self size y self.parent[x]=y self.parent[x] self.parent self parent x y self.size[y]+=self.size[x] self.size[y] self.size self size y self.size[x] self.size self size x self self x x y y def get_group_size(self,x):
    return self.size[self.root(x)]
  
   get_group_size return self.size[self.root(x)] self.size[self.root(x)] self.size self size self.root(x) self.root self root x self self x x def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
   get_roots r=set() r set() set for i in range(self.N):
      r.add(self.root(i))
     i range(self.N) range self.N self N r.add(self.root(i)) r.add r add self.root(i) self.root self root i return r r self self def show_parent(self):
    print(self.parent)
    
   show_parent print(self.parent) print self.parent self parent self self def show_size(self):
    print(self.size) show_size print(self.size) print self.size self size self self UF=UnionFind(N) UF UnionFind(N) UnionFind N for i,j in target:
  UF.unite(i,j)
   i j target UF.unite(i,j) UF.unite UF unite i j print(len(UF.get_roots())) print len(UF.get_roots()) len UF.get_roots() UF.get_roots UF get_roots UF=UnionFind(N) UnionFind(N) UF pq=None None pq pq=item[0] item[0] pq ball=[None] * N [None] * N ball N=int(input()) int(input()) N ball=sorted(ball,key=lambda x:(x[0],x[1])) sorted(ball,key=lambda x:(x[0],x[1])) ball class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size) class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size) UnionFind dic = defaultdict(list) defaultdict(list) dic target=[] [] target target = item[1] item[1] target
# まず、xの値でソート（同値の場合はyでソート）する。
# この状態で、全ての2点について、x,yの差を求める
# 差の情報(p,q)の回数が最も大きいものが答えの候補
# (p,q)で到達できる点にはコスト0で行けるグラフの最短距離を解く

N=int(input())
ball=[None] * N
for i in range(N):
  ball[i] = list(map(int,input().split()))

ball=sorted(ball,key=lambda x:(x[0],x[1]))

from collections import defaultdict
dic = defaultdict(list)

for i in range(N-1):
  for j in range(i+1,N):
    # 点iから点jへは(p,q)で到達できる
    dic[(ball[j][0] - ball[i][0],ball[j][1] - ball[i][1])].append((i,j))

pq=None
target=[]
for item in dic.items():
  if len(item[1]) > len(target):
    target = item[1]
    pq=item[0]
    
# targetの要素で、同じ点を持つものは結合して1つの点にできる。
# UnionFind

# 0-indexed
class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(self.root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size)

UF=UnionFind(N)
for i,j in target:
  UF.unite(i,j)
  
print(len(UF.get_roots()))