from collections import deque
from typing import Tuple, List
class Dinic:
def __init__(self, n: int):
self.n = n
self.links: List[List[List[int]]] = [[] for _ in range(n)]
def add_link(self, from_: int, to: int, capacity: int) -> None:
self.links[from_].append([capacity, to, len(self.links[to]), 1])
self.links[to].append([0, from_, len(self.links[from_]) - 1, 0])
def bfs(self, s: int) -> List[int]:
depth = [-1] * self.n
depth[s] = 0
q = deque([s])
while q:
v = q.popleft()
for cap, to, rev, _ in self.links[v]:
if cap > 0 and depth[to] < 0:
depth[to] = depth[v] + 1
q.append(to)
return depth
def dfs(self, s: int, t: int, depth: List[int], progress: List[int], link_counts: List[int]) -> int:
links = self.links
stack = [s]
while stack:
v = stack[-1]
if v == t:
break
for i in range(progress[v], link_counts[v]):
progress[v] = i
cap, to, rev, _ = links[v][i]
if cap == 0 or depth[v] >= depth[to] or progress[to] >= link_counts[to]:
continue
stack.append(to)
break
else:
progress[v] += 1
stack.pop()
else:
return 0
f = 1 << 60
fwd_links = []
bwd_links = []
for v in stack[:-1]:
cap, to, rev, _ = link = links[v][progress[v]]
f = min(f, cap)
fwd_links.append(link)
bwd_links.append(links[to][rev])
for link in fwd_links:
link[0] -= f
for link in bwd_links:
link[0] += f
return f
def max_flow(self, s: int, t: int) -> int:
link_counts = list(map(len, self.links))
flow = 0
while True:
depth = self.bfs(s)
if depth[t] < 0:
break
progress = [0] * self.n
current_flow = self.dfs(s, t, depth, progress, link_counts)
while current_flow > 0:
flow += current_flow
current_flow = self.dfs(s, t, depth, progress, link_counts)
return flow
def cut_edges(self, s: int) -> List[Tuple[int, int]]:
q = [s]
reachable = [0] * self.n
reachable[s] = 1
while q:
v = q.pop()
for cap, u, li, _ in self.links[v]:
if cap == 0 or reachable[u]:
continue
reachable[u] = 1
q.append(u)
edges = []
for v in range(self.n):
if reachable[v] == 0:
continue
for cap, u, li, orig in self.links[v]:
if orig == 1 and reachable[u] == 0:
edges.append((v, u))
return edges
h, w = map(int, input().split())
field = [input() for _ in range(h)]
cells = set()
cameras = set()
camera_ud = [-1] * (h * w)
camera_lr = [-1] * (h * w)
for i in range(h):
for j in range(w):
if field[i][j] == '#':
continue
key = i * w + j
cells.add(key)
if i == 0 or field[i - 1][j] == '#':
camera_key = key << 1
camera_ud[key] = camera_key
cameras.add(camera_key)
else:
camera_ud[key] = camera_ud[key - w]
if j == 0 or field[i][j - 1] == '#':
camera_key = (key << 1) + 1
camera_lr[key] = camera_key
cameras.add(camera_key)
else:
camera_lr[key] = camera_lr[key - 1]
n = len(cameras)
s = n
t = s + 1
mf = Dinic(n + 2)
camera_idx = {c: i for i, c in enumerate(cameras)}
INF = 1 << 60
for key in cameras:
u = camera_idx[key]
if key & 1:
mf.add_link(u, t, 1)
else:
mf.add_link(s, u, 1)
for key in cells:
u = camera_idx[camera_ud[key]]
v = camera_idx[camera_lr[key]]
mf.add_link(u, v, INF)
ans = mf.max_flow(s, t)
print(ans)