#Thansk for aaaaaaaaaa2230 #URL:https://atcoder.jp/contests/practice2/submissions/17017319 import sys from collections import deque class MaxFlow: class Edge: def __init__(self,target,cap,base,direct): self.target = target self.cap = cap self.flow=0 self.base=base self.direct=direct self.rev = None def __str__(self): if self.direct==1: return "[S](target:{}, flow/cap:{}/{})".format(self.target,self.flow,self.base) else: return "[T](source:{}, flow/cap:{}/{})".format(self.target,self.flow,self.base) __repr__=__str__ def __init__(self,N): """ N 頂点からなる Flow 場を生成する. """ self.N = N self.graph = [[] for _ in range(N)] self.old_flow=0 def add_edge(self,u,v, cap): """ 容量が cap である有向辺 u→v を加える. u,v: 頂点 cap: 容量 """ graph = self.graph edge = self.Edge(v,cap,cap,1) edge2 = self.Edge(u,0,cap,-1) edge.rev = edge2 edge2.rev = edge graph[u].append(edge) graph[v].append(edge2) def __bfs(self, s, t): level = self.level = [self.N]*self.N q = deque([s]) level[s] = 0 while q: now = q.popleft() lw = level[now]+1 for e in self.graph[now]: if e.cap and level[e.target]> lw: level[e.target] = lw if e.target == t: return True q.append(e.target) return False def __dfs(self, s, t, up): graph = self.graph it = self.it level = self.level st = deque([t]) while st: v = st[-1] if v == s: st.pop() flow = up for w in st: e = graph[w][it[w]].rev flow = min(flow, e.cap) for w in st: e = graph[w][it[w]] e.cap += flow e.flow-=flow e.rev.cap -= flow e.rev.flow+=flow return flow lv = level[v]-1 while it[v] < len(graph[v]): e = graph[v][it[v]] re = e.rev if re.cap == 0 or lv != level[e.target]: it[v] += 1 continue st.append(e.target) break if it[v] == len(graph[v]): st.pop() level[v] = self.N return 0 def max_flow(self,source,target,flow_limit=float("inf")): """ source から target に流す最大流の大きさを出力する. source, target: 頂点 flow_limit: "追加で流す" 最大流の上限 """ Flow=0 while Flow < flow_limit and self.__bfs(source,target): self.it=[0]*self.N while Flow=0) 点を得るという条件を追加する. 0<=x=0 """ assert a>=0 self.indivi.append([None,None]) self.ver_num+=1 self.base+=a self.indivi[-1][0]=-a for x in X: assert 0<=x=0) 点を得るという条件を追加する. 0<=x=0 """ assert a>=0 self.indivi.append([None,None]) self.ver_num+=1 self.base+=a self.indivi[-1][1]=-a for x in X: assert 0<=x=0) 点を得るという条件を追加する. 0<=x,y=0 """ assert 0<=x=0 self.set_all_zero([x,y],a) self.set_all_one([x,y],a) def ban_zero(self,x): """ h(x)=0 となることを禁止する. (実行したら -inf 点になる) 0<=x=0: base+=self.indivi[i][0] F.add_edge(self.source,i,self.indivi[i][0]) else: F.add_edge(i,self.target,-self.indivi[i][0]) if self.indivi[i][1]>=0: base+=self.indivi[i][1] F.add_edge(i,self.target,self.indivi[i][1]) else: F.add_edge(self.source,i,-self.indivi[i][1]) for i in range(self.target+1,self.ver_num): if self.indivi[i][0]!=None: F.add_edge(self.source,i,-self.indivi[i][0]) if self.indivi[i][1]!=None: F.add_edge(i,self.target,-self.indivi[i][1]) for x,y,c in self.mutual: F.add_edge(x,y,c) alpha=F.max_flow(self.source,self.target) if Mode==0: return base-alpha else: return base-alpha,F.min_cut(self.source)[:self.N] #================================================== def f(i,j): return i*W+j #================================================== H,W=map(int,input().split()) G=[] for _ in range(H): G.append(list(map(int,input().split()))) R=list(map(int,input().split())) C=list(map(int,input().split())) P=Project_Selection_Problem(H*W) for i in range(H): for j in range(W): P.set_one(f(i,j),-G[i][j]) for i in range(H): P.set_all_one(range(i*W,(i+1)*W),R[i]) for j in range(W): P.set_all_one(range(j,H*W,W),C[j]) print(P.solve(0))