1+ # thanks: https://atcoder.jp/contests/practice2/submissions/16784996
2+
13#!usr/bin/env python3
24from collections import defaultdict , deque , Counter , OrderedDict
35from bisect import bisect_left , bisect_right
@@ -19,13 +21,13 @@ def LR(n): return [L() for _ in range(n)]
1921def IR (n ): return [I () for _ in range (n )]
2022def LIR (n ): return [LI () for _ in range (n )]
2123def LIR1 (n ): return [LI1 () for _ in range (n )]
22- def SR (n ): return [SL () for _ in range (n )]
24+ def SLR (n ): return [SL () for _ in range (n )]
2325def LSR (n ): return [LS () for _ in range (n )]
2426
2527def perm (n , r ): return math .factorial (n ) // math .factorial (r )
2628def comb (n , r ): return math .factorial (n ) // (math .factorial (r ) * math .factorial (n - r ))
2729
28- def make_list (n , * args , default = 0 ): return [make_list (* args , default = default ) for _ in range (n )] if len ( args ) > 0 else [default for _ in range (n )]
30+ def make_list (n , * args , default = 0 ): return [make_list (* args , default = default ) for _ in range (n )] if args else [default for _ in range (n )]
2931
3032dire = [[1 , 0 ], [0 , 1 ], [- 1 , 0 ], [0 , - 1 ]]
3133dire8 = [[1 , 0 ], [1 , 1 ], [0 , 1 ], [- 1 , 1 ], [- 1 , 0 ], [- 1 , - 1 ], [0 , - 1 ], [1 , - 1 ]]
@@ -36,8 +38,127 @@ def make_list(n, *args, default=0): return [make_list(*args, default=default) fo
3638
3739sys .setrecursionlimit (1000000 )
3840
41+ class MaxFlowGraph :
42+ def __init__ (self , N ):
43+ self .N = N
44+ self .graph = [[] for _ in range (N )]
45+ self .capacities = [dict () for _ in range (N )]
46+
47+ def add_edge (self , v , w , cap = 1 ):
48+ self .graph [v ].append (w )
49+ self .graph [w ].append (v )
50+ self .capacities [v ][w ] = cap
51+ self .capacities [w ][v ] = 0
52+
53+ def bfs (self , s , t ):
54+ self .level = [- 1 ] * self .N
55+ q = deque ([s ])
56+ self .level [s ] = 0
57+ while q :
58+ v = q .popleft ()
59+ for w , cap in self .capacities [v ].items ():
60+ if cap and self .level [w ] == - 1 :
61+ self .level [w ] = self .level [v ] + 1
62+ if w == t : return True
63+ q .append (w )
64+ return False
65+
66+ def dfs (self , s , t , limit ):
67+ st = [t ]
68+ while st :
69+ v = st [- 1 ]
70+ if v == s : break
71+ #vから行ける全ての頂点について
72+ while self .it [v ] < len (self .graph [v ]):
73+ # w -> v の cap
74+ w = self .graph [v ][self .it [v ]]
75+ cap = self .capacities [w ][v ]
76+ if cap and self .level [w ] != - 1 and self .level [v ] > self .level [w ]:
77+ st .append (w )
78+ break
79+ self .it [v ] += 1
80+ else :
81+ st .pop ()
82+ self .level [v ] = self .N
83+ else : return 0
84+
85+ flow = min (limit , min (self .capacities [st [i + 1 ]][st [i ]] for i in range (len (st ) - 2 )))
86+ for i in range (len (st ) - 1 ):
87+ self .capacities [st [i ]][st [i + 1 ]] += flow
88+ self .capacities [st [i + 1 ]][st [i ]] -= flow
89+ return flow
90+
91+ def flow (self , s , t , flow_limit = 18446744073709551615 ):
92+ flow = 0
93+ while flow < flow_limit and self .bfs (s , t ):
94+ self .it = [0 ]* self .N
95+ while flow < flow_limit :
96+ f = self .dfs (s , t , flow_limit - flow )
97+ if not f : break
98+ flow += f
99+ return flow
100+
101+ def min_cut (self , s ):
102+ visited = [False ]* self .N
103+ q = [s ]
104+ while q :
105+ v = q .pop ()
106+ visited [v ] = True
107+ for w , cap in self .capacities [v ].items ():
108+ if cap and not visited [w ]:
109+ q .append (w )
110+
39111def main ():
40- N = I ()
112+ N , M = LI ()
113+ S = SLR (N )
114+ g = MaxFlowGraph (N * M + 2 )
115+
116+ s = N * M
117+ t = N * M + 1
118+
119+ # 偶数はblack, 奇数はwhiteとして市松模様に塗る、二部グラフの最大マッチング問題
120+ # s -> black -> white -> t の辺を張って最大流を求める
121+ for y in range (N ):
122+ for x in range (M ):
123+ # black
124+ if (y + x ) % 2 == 0 :
125+ g .add_edge (s , M * y + x )
126+ for dy , dx in [[1 , 0 ], [0 , 1 ]]:
127+ ny , nx = y + dy , x + dx
128+ if 0 <= ny < N and 0 <= nx < M and S [y ][x ] == "." and S [ny ][nx ] == "." :
129+ g .add_edge (M * y + x , M * ny + nx )
130+ # white
131+ else :
132+ g .add_edge (M * y + x , t )
133+ for dy , dx in [[1 , 0 ], [0 , 1 ]]:
134+ ny , nx = y + dy , x + dx
135+ if 0 <= ny < N and 0 <= nx < M and S [y ][x ] == "." and S [ny ][nx ] == "." :
136+ g .add_edge (M * ny + nx , M * y + x )
137+
138+ print (g .flow (s , t ))
139+
140+ # blackから考える
141+ for u in range (N * M + 2 ):
142+ uy , ux = divmod (u , M )
143+ if (uy + ux ) % 2 == 1 : continue
144+
145+ for v , cap in g .capacities [u ].items ():
146+ if cap != 0 : continue
147+ vy , vx = divmod (v , M )
148+ if u != s and u != t and v != s and v != t :
149+ if uy - 1 == vy :
150+ S [uy ][ux ], S [vy ][vx ] = "^" , "v"
151+ elif uy + 1 == vy :
152+ S [uy ][ux ], S [vy ][vx ] = "v" , "^"
153+ elif ux + 1 == vx :
154+ S [uy ][ux ], S [vy ][vx ] = ">" , "<"
155+ elif ux - 1 == vx :
156+ S [uy ][ux ], S [vy ][vx ] = "<" , ">"
157+
158+ for p in S :
159+ print ("" .join (p ))
160+
161+
41162
42163if __name__ == '__main__' :
43164 main ()
0 commit comments