import sys sys.setrecursionlimit(10**6) from collections import deque class HopcroftKarp: def __init__(self, N1, N2): self.N1 = N1 self.N2 = N2 self.G = [[] for _ in range(self.N1+1)] self.pair1 = [0]*(self.N1+1) self.pair2 = [0]*(self.N2+1) self.matching_size = -1 def add_edge(self, fr, to): self.G[fr].append(to) def bfs(self): que = deque() for i in range(1, self.N1+1): if self.pair1[i] == 0: self.dist[i] = 0 que.append(i) else: self.dist[i] = INF self.dist[0] = INF while que: n = que.popleft() if self.dist[n] < self.dist[0]: for v in self.G[n]: if self.dist[self.pair2[v]] == INF: self.dist[self.pair2[v]] = self.dist[n]+1 que.append(self.pair2[v]) return self.dist[0] != INF def dfs(self, n): if n != 0: for v in self.G[n]: if self.dist[self.pair2[v]] == self.dist[n]+1: if self.dfs(self.pair2[v]): self.pair2[v] = n self.pair1[n] = v return True self.dist[n] = INF return False return True def flow(self): if self.matching_size != -1: return self.matching_size self.dist = [0]*(self.N1+1) ans = 0 while self.bfs(): for i in range(1, self.N1+1): if self.pair1[i] == 0 and self.dfs(i): ans += 1 self.matching_size = ans return ans def get_matching(self): if self.matching_size == -1: self.flow() ans = [] for i in range(1, self.N1+1): if self.pair1[i] != 0: ans.append((i, self.pair1[i])) return ans def minimum_vertex_cover(self): if self.matching_size == -1: self.flow() return self.matching_size def maximum_independent_set(self): return self.N1+self.N2-self.minimum_vertex_cover() def minimum_edge_cover(self): F = [False]*(self.N1+self.N2+1) for n in range(1, self.N1+1): F[n] = True for v in self.G[n]: F[self.N1+v] = True if sum(F) < self.N1+self.N2: return -1 if self.matching_size == -1: self.flow() return self.N1+self.N2-self.matching_size def preparation(self): if self.matching_size == -1: self.flow() L = self.N1+self.N2 G = [[] for _ in range(L+1)] for n in range(1, self.N1+1): for v in self.G[n]: if self.pair1[n] == v: G[self.N1+v].append(n) else: G[n].append(self.N1+v) visited = [False]*(L+1) que = deque() for i in range(1, self.N1+1): if self.pair1[i] == 0: visited[i] = True que.append(i) while que: n = que.popleft() for v in G[n]: if not visited[v]: visited[v] = True que.append(v) return visited def get_minimum_vertex_cover(self): visited = self.preparation() ans1 = [] ans2 = [] for i in range(1, self.N1+self.N2+1): if i <= self.N1 and not visited[i]: ans1.append(i) elif self.N1+1 <= i and visited[i]: ans2.append(i-self.N1) return ans1, ans2 def get_maximum_independent_set(self): visited = self.preparation() ans1 = [] ans2 = [] for i in range(1, self.N1+self.N2+1): if i <= self.N1 and visited[i]: ans1.append(i) elif self.N1+1 <= i and not visited[i]: ans2.append(i-self.N1) return ans1, ans2 def get_minimum_edge_cover(self): cnt = self.minimum_edge_cover() if cnt == -1: return None ans = [] pair = [-1]*(self.N1+self.N2+1) for n in range(1, self.N1+1): pair[n] = self.G[n][0] for v in self.G[n]: if pair[self.N1+v] == -1: pair[self.N1+v] = n for i in range(1, self.N1+self.N2+1): if i <= self.N1 and self.pair1[i] != 0: ans.append((i, self.pair1[i])) elif i <= self.N1 and self.pair1[i] == 0: ans.append((i, pair[i])) elif self.N1+1 <= i and self.pair2[i-self.N1] == 0: ans.append((pair[i], i-self.N1)) return ans INF = 1<<60 N, M = map(int, input().split()) edge = [list(map(int, input().split())) for _ in range(M)] ans = -N H = HopcroftKarp(N, N) F = [False]*N for u, v in edge: F[u-1] = True F[v-1] = True H.add_edge(u, v) H.add_edge(v, u) sumF = sum(F) if sumF != N-1: ans += H.flow()*2 else: res = H.flow() if res == N-1: res -= 1 ans += res*2 print(ans)