結果
問題 | No.177 制作進行の宮森あおいです! |
ユーザー |
👑 |
提出日時 | 2020-06-15 00:14:36 |
言語 | Lua (LuaJit 2.1.1734355927) |
結果 |
AC
|
実行時間 | 15 ms / 2,000 ms |
コード長 | 15,004 bytes |
コンパイル時間 | 32 ms |
コンパイル使用メモリ | 6,688 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-06-28 03:27:32 |
合計ジャッジ時間 | 886 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 13 |
ソースコード
local mmi, mma = math.min, math.maxlocal MPM = {}MPM.initialize = function(self, n, spos, tpos)self.n = nself.spos, self.tpos = spos, tpos-- edge_dst[src][i] := dstself.edge_dst = {}-- edge_cap[src][i] := capacity from src to edge_dst[src][i]self.edge_cap = {}-- edge_dst_invedge_idx[src][i] := "j" where edge_dst[dst][j] == src-- in this case, edge_dst_invedge_idx[dst][j] should be "i".self.edge_dst_invedge_idx = {}-- level[v] := length from spos. level[spos] := 1self.level = {}-- level_vertex_count[i] := count of vertexes that levels are iself.level_vertex_count = {}-- sub_graph_v[i] := list of vertexes that are contained in the sub-graph.self.sub_graph_v = {}-- sub_graph_size := the size of sub_graph_v.-- may not equal to #sub_graph_v (because not cleared).self.sub_graph_size = 0-- sub_graph_flag[v] := whether to contains the vertex v in the sub-graph or notself.sub_graph_flag = {}-- send[v] := sum of sendable amount from v to other vertexes in the sub-graphself.send = {}-- receive[v] := sum of receivable amount toward v from other vertexes in the sub-graphself.receive = {}-- sub_edge_idxes[src][i] := edge (from v) using in the sub-graph.-- for example, if sub_edge_idxes[src][i] is j,-- the edge from src to dst (= edge_dst[src][j]) contains in the sub-graph.self.sub_edge_idxes = {}-- sub_edge_cnt[src] := the size of sub_edge_idxes[src].-- may not equal to #sub_edge_idxes[src] (because not cleared).self.sub_edge_cnt = {}-- sub_invedge_idxes[dst] := edge (to dst) using in the sub-graph.-- for example, if sub_invedge_idxes[dst][i] is j,-- the src is edge_dst[dst][j], and the edge index (from src to dst) is k := edge_dst_invedge_idx[dst][j].-- so edge_dst[src][k] is the edge from src to dst using in the sub-graph.self.sub_invedge_idxes = {}-- sub_invedge_cnt[dst] := the size of sub_invedge_idxes[dst].-- may not equal to #sub_invedge_idxes[dst] (because not cleared).self.sub_invedge_cnt = {}-- flow_route[v] := [for "flowToT"] whether to contain in the route from weak_vertex to tpos.self.flow_route = {}-- actual_flow_amount[v] := [for "flowToT"] send amount from vself.actual_flow_amount = {}for i = 1, n doself.edge_dst[i] = {}self.edge_cap[i] = {}self.edge_dst_invedge_idx[i] = {}self.level[i] = 0self.level_vertex_count[i] = 0self.sub_graph_flag[i] = falseself.send[i] = 0self.receive[i] = 0self.sub_edge_idxes[i] = {}self.sub_edge_cnt[i] = 0self.sub_invedge_idxes[i] = {}self.sub_invedge_cnt[i] = 0self.flow_route[i] = falseself.actual_flow_amount[i] = 0endendMPM.addEdge = function(self, src, dst, cap, invcap)if not invcap then invcap = 0 endtable.insert(self.edge_dst[src], dst)table.insert(self.edge_cap[src], cap)table.insert(self.edge_dst_invedge_idx[src], 1 + #self.edge_dst[dst])table.insert(self.edge_dst[dst], src)table.insert(self.edge_cap[dst], invcap)table.insert(self.edge_dst_invedge_idx[dst], #self.edge_dst[src])endMPM.makeSubGraph = function(self)local inf = self.n + 2local level, sub_graph_flag = self.level, self.sub_graph_flaglocal edge_dst, edge_cap = self.edge_dst, self.edge_caplocal edge_dst_invedge_idx = self.edge_dst_invedge_idxlocal send, receive = self.send, self.receivelocal sub_graph_v = self.sub_graph_vlocal sub_edge_idxes, sub_edge_cnt = self.sub_edge_idxes, self.sub_edge_cntlocal sub_invedge_idxes, sub_invedge_cnt = self.sub_invedge_idxes, self.sub_invedge_cntlocal level_vertex_count = self.level_vertex_countfor i = 1, self.n dolevel[i] = infsub_graph_flag[i] = falsesend[i], receive[i] = 0, 0sub_edge_cnt[i] = 0sub_invedge_cnt[i] = 0level_vertex_count[i] = 0end-- BFSlevel[self.spos] = 1local taskcnt, done = 1, 0sub_graph_v[1] = self.sposlocal reached = falsewhile done < taskcnt dodone = done + 1local src = sub_graph_v[done]if src == self.tpos then reached = true break endfor i = 1, #edge_dst[src] dolocal cap = edge_cap[src][i]if 0 < cap thenlocal dst = edge_dst[src][i]if level[dst] == inf thenlevel[dst] = level[src] + 1taskcnt = taskcnt + 1sub_graph_v[taskcnt] = dstelseif level[dst] == level[src] + 1 thenendendendendif not reached thenself.sub_graph_size = 0return falseend-- restore routesub_graph_flag[self.tpos] = truelocal curlevel = level[self.tpos]while curlevel == level[sub_graph_v[taskcnt]] dotaskcnt = taskcnt - 1endfor isrc = taskcnt, 1, -1 dolocal src = sub_graph_v[isrc]for i = 1, #edge_dst[src] dolocal dst, cap = edge_dst[src][i], edge_cap[src][i]if 0 < cap and sub_graph_flag[dst]and level[dst] == level[src] + 1 thensub_graph_flag[src] = truelocal edgecnt = sub_edge_cnt[src] + 1sub_edge_cnt[src] = edgecntsub_edge_idxes[src][edgecnt] = isub_invedge_cnt[dst] = sub_invedge_cnt[dst] + 1sub_invedge_idxes[dst][sub_invedge_cnt[dst]] = edge_dst_invedge_idx[src][i]send[src] = send[src] + capreceive[dst] = receive[dst] + capendendif not sub_graph_flag[src] thenfor i = 1, #edge_dst[src] dolocal dst = edge_dst[src][i]local cap = edge_cap[src][i]if 0 < cap and level[dst] == level[src] + 1 thensend[src] = send[src] - capreceive[dst] = receive[dst] - capendendendend-- remove unused vertex from "taskcnt" and set as sub_graph_sizelocal nodecnt = 1for i = 1, taskcnt dolocal v = sub_graph_v[i]if sub_graph_flag[v] thensub_graph_v[nodecnt] = vlocal lv = level[v]level_vertex_count[lv] = level_vertex_count[lv] + 1nodecnt = nodecnt + 1endendif sub_graph_v[nodecnt - 1] == self.tpos thennodecnt = nodecnt - 1elsesub_graph_v[nodecnt] = self.tposlocal lv = level[self.tpos]level_vertex_count[lv] = level_vertex_count[lv] + 1endself.sub_graph_size = nodecntreturn trueendMPM.subGraphConnected = function(self)local max_level = self.level[self.tpos]local level_vertex_count = self.level_vertex_countfor i = 1, max_level doif level_vertex_count[i] <= 0 then return false endendreturn trueendMPM.findWeakVertex = function(self)local sub_graph_v = self.sub_graph_vlocal sub_graph_size = self.sub_graph_sizelocal send, receive = self.send, self.receivelocal min_vertex = self.sposlocal min_potential = send[min_vertex]if receive[self.tpos] < min_potential thenmin_vertex = self.tposmin_potential = receive[min_vertex]endfor i = 2, sub_graph_size - 1 dolocal v = sub_graph_v[i]assert(v ~= self.tpos)local min_v = mmi(send[v], receive[v])if min_v < min_potential thenmin_potential, min_vertex = min_v, vendendreturn min_vertex, min_potentialendMPM.flowToT = function(self, weak_vertex, potential)if weak_vertex == self.tpos then return endlocal sub_graph_flag = self.sub_graph_flaglocal edge_dst, edge_cap = self.edge_dst, self.edge_caplocal edge_dst_invedge_idx = self.edge_dst_invedge_idxlocal sub_graph_v = self.sub_graph_vlocal sub_graph_size = self.sub_graph_sizelocal sub_edge_cnt = self.sub_edge_cntlocal sub_edge_idxes = self.sub_edge_idxeslocal send, receive = self.send, self.receivelocal level = self.levellocal flow_route = self.flow_routelocal actual_flow_amount = self.actual_flow_amountlocal tpos = self.tposfor i = 1, sub_graph_size dolocal v = sub_graph_v[i]flow_route[v] = falseactual_flow_amount[v] = 0endflow_route[weak_vertex] = trueactual_flow_amount[weak_vertex] = potentiallocal weak_vertex_level = level[weak_vertex]local max_level = level[tpos]for iv = 1, sub_graph_size dolocal src = sub_graph_v[iv]local lv = level[src]if lv == max_level then break endlocal need_to_send = actual_flow_amount[src]if flow_route[src] and 0 < need_to_send thensend[src] = send[src] - need_to_sendlocal sub_edge_idxes_src = sub_edge_idxes[src]local dsts, caps, invidxes = edge_dst[src], edge_cap[src], edge_dst_invedge_idx[src]local used = 0-- use edge in descending order, to remove used edges quicklyfor j = sub_edge_cnt[src], 1, -1 dolocal edgeidx = sub_edge_idxes_src[j]local dst, cap = dsts[edgeidx], caps[edgeidx]local actual_flow = mmi(cap, need_to_send)receive[dst] = receive[dst] - actual_flowcaps[edgeidx] = caps[edgeidx] - actual_flowneed_to_send = need_to_send - actual_flowflow_route[dst] = trueactual_flow_amount[dst] = actual_flow_amount[dst] + actual_flowlocal inv_edge_idx = invidxes[edgeidx]edge_cap[dst][inv_edge_idx] = edge_cap[dst][inv_edge_idx] + actual_flowif caps[edgeidx] == 0 thenused = used + 1endif need_to_send == 0 thenbreakendendsub_edge_cnt[src] = sub_edge_cnt[src] - usedendendendMPM.flowFromS = function(self, weak_vertex, potential)if weak_vertex == self.spos then return endlocal sub_graph_flag = self.sub_graph_flaglocal edge_dst, edge_cap = self.edge_dst, self.edge_caplocal edge_dst_invedge_idx = self.edge_dst_invedge_idxlocal sub_graph_v = self.sub_graph_vlocal sub_graph_size = self.sub_graph_sizelocal sub_edge_cnt = self.sub_edge_cntlocal sub_edge_idxes = self.sub_edge_idxeslocal sub_invedge_idxes = self.sub_invedge_idxeslocal sub_invedge_cnt = self.sub_invedge_cntlocal send, receive = self.send, self.receivelocal level = self.levellocal flow_route = self.flow_routelocal actual_flow_amount = self.actual_flow_amountlocal spos = self.sposfor i = 1, sub_graph_size dolocal v = sub_graph_v[i]flow_route[v] = falseactual_flow_amount[v] = 0endflow_route[weak_vertex] = trueactual_flow_amount[weak_vertex] = potentiallocal weak_vertex_level = level[weak_vertex]local max_level = level[tpos]for iv = sub_graph_size, 1, -1 dolocal dst = sub_graph_v[iv]local lv = level[dst]if lv == 1 then break endlocal need_to_receive = actual_flow_amount[dst]if flow_route[dst] and 0 < need_to_receive thenreceive[dst] = receive[dst] - need_to_receivelocal sub_invedge_idxes_dst = sub_invedge_idxes[dst]local srcs = edge_dst[dst]local inv_invidxes = edge_dst_invedge_idx[dst]-- local dsts, caps, invidxes = edge_dst[src], edge_cap[src], edge_dst_invedge_idx[src]local used = 0-- use edge in descending order, to remove used edges quicklyfor j = sub_invedge_cnt[dst], 1, -1 dolocal invedgeidx = sub_invedge_idxes_dst[j]local src = srcs[invedgeidx]local edgeidx = inv_invidxes[invedgeidx]assert(edge_dst[src][edgeidx] == dst)local cap = edge_cap[src][edgeidx]local actual_flow = mmi(cap, need_to_receive)send[src] = send[src] - actual_flowedge_cap[src][edgeidx] = edge_cap[src][edgeidx] - actual_flowneed_to_receive = need_to_receive - actual_flowflow_route[src] = trueactual_flow_amount[src] = actual_flow_amount[src] + actual_flowedge_cap[dst][invedgeidx] = edge_cap[dst][invedgeidx] + actual_flowif edge_cap[src][edgeidx] == 0 thenused = used + 1endif need_to_receive == 0 thenbreakendendsub_invedge_cnt[dst] = sub_invedge_cnt[dst] - usedendendendMPM.updateSubGraph = function(self)local sub_graph_v = self.sub_graph_vlocal sub_graph_size = self.sub_graph_sizelocal sub_graph_flag = self.sub_graph_flaglocal send, receive = self.send, self.receivelocal spos, tpos = self.spos, self.tposlocal level = self.levellocal level_vertex_count = self.level_vertex_countlocal sub_edge_idxes = self.sub_edge_idxeslocal sub_edge_cnt = self.sub_edge_cntlocal edge_dst = self.edge_dstlocal sub_invedge_idxes = self.sub_invedge_idxeslocal sub_invedge_cnt = self.sub_invedge_cntlocal nodecnt = 0for i = 1, sub_graph_size dolocal v = sub_graph_v[i]local valid = trueif v ~= spos and receive[v] <= 0 then valid = false endif v ~= tpos and send[v] <= 0 then valid = false endif valid thenlocal sub_invedge_idxes_v = sub_invedge_idxes[v]valid = falsefor j = 1, sub_invedge_cnt[v] dolocal ei = sub_invedge_idxes_v[j]local src = edge_dst[v][ei]if sub_graph_flag[src] then valid = true break endendendif valid thennodecnt = nodecnt + 1sub_graph_v[nodecnt] = velsesub_graph_flag[v] = falselocal lv = level[v]level_vertex_count[lv] = level_vertex_count[lv] - 1endendsub_graph_size = nodecntfor i = sub_graph_size, 1, -1 dolocal v = sub_graph_v[i]local valid = falselocal sub_edge_idxes_v = sub_edge_idxes[v]for j = 1, sub_edge_cnt[v] dolocal ei = sub_edge_idxes_v[j]local dst = edge_dst[v][ei]if sub_graph_flag[dst] then valid = true break endendif not valid thensub_graph_flag[v] = falselocal lv = level[v]level_vertex_count[lv] = level_vertex_count[lv] - 1endendnodecnt = 0for i = 1, sub_graph_size dolocal v = sub_graph_v[i]if sub_graph_v[v] thennodecnt = nodecnt + 1sub_graph_v[nodecnt] = vendendself.sub_graph_size = nodecntendMPM.partialwork = function(self)local sum = 0while(self:subGraphConnected()) dolocal weak_vertex, potential = self:findWeakVertex()self:flowToT(weak_vertex, potential)self:flowFromS(weak_vertex, potential)self:updateSubGraph()sum = sum + potentialendreturn sumendMPM.getMaxFlow = function(self)local ret = 0while(self:makeSubGraph()) doret = ret + self:partialwork()endreturn retend-- yukicoder 177local w = io.read("*n")local n = io.read("*n")local j = {}for i = 1, n doj[i] = io.read("*n")endlocal m = io.read("*n")local c = {}for i = 1, m doc[i] = io.read("*n")endMPM:initialize(n + m + 2, n + m + 1, n + m + 2)for i = 1, n doif 0 < j[i] thenMPM:addEdge(n + m + 1, i, j[i])endendfor i = 1, m doif 0 < c[i] thenMPM:addEdge(n + i, n + m + 2, c[i])endendlocal tmp = {}local inf = 1000000007for i = 1, m dolocal q = io.read("*n")for j = 1, n dotmp[j] = trueendfor iq = 1, q dolocal x = io.read("*n")tmp[x] = falseendfor j = 1, n doif tmp[j] thenMPM:addEdge(j, n + i, inf)endendendlocal ret = MPM:getMaxFlow()-- print(ret)print(w <= ret and "SHIROBAKO" or "BANSAKUTSUKITA")