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)