結果

問題 No.957 植林
ユーザー tktk_snsntktk_snsn
提出日時 2021-01-07 22:51:37
言語 PyPy3
(7.3.15)
結果
TLE  
実行時間 -
コード長 3,961 bytes
コンパイル時間 160 ms
コンパイル使用メモリ 82,384 KB
実行使用メモリ 234,884 KB
最終ジャッジ日時 2024-11-14 04:12:47
合計ジャッジ時間 116,224 ms
ジャッジサーバーID
(参考情報)
judge4 / judge2
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 44 ms
62,480 KB
testcase_01 AC 42 ms
200,436 KB
testcase_02 AC 41 ms
61,272 KB
testcase_03 TLE -
testcase_04 TLE -
testcase_05 TLE -
testcase_06 TLE -
testcase_07 TLE -
testcase_08 TLE -
testcase_09 TLE -
testcase_10 TLE -
testcase_11 TLE -
testcase_12 TLE -
testcase_13 AC 987 ms
145,116 KB
testcase_14 TLE -
testcase_15 TLE -
testcase_16 TLE -
testcase_17 TLE -
testcase_18 TLE -
testcase_19 TLE -
testcase_20 TLE -
testcase_21 TLE -
testcase_22 TLE -
testcase_23 TLE -
testcase_24 TLE -
testcase_25 TLE -
testcase_26 TLE -
testcase_27 TLE -
testcase_28 TLE -
testcase_29 TLE -
testcase_30 TLE -
testcase_31 TLE -
testcase_32 TLE -
testcase_33 TLE -
testcase_34 TLE -
testcase_35 TLE -
testcase_36 TLE -
testcase_37 TLE -
testcase_38 TLE -
testcase_39 TLE -
testcase_40 TLE -
testcase_41 AC 220 ms
144,188 KB
testcase_42 AC 217 ms
143,436 KB
testcase_43 AC 269 ms
159,944 KB
testcase_44 AC 326 ms
160,692 KB
testcase_45 AC 41 ms
55,668 KB
testcase_46 AC 41 ms
54,708 KB
testcase_47 AC 41 ms
234,884 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

from collections import deque
import sys
input = sys.stdin.buffer.readline
sys.setrecursionlimit(10 ** 7)
inf = 10**15


class MF_graph(object):
    def __init__(self, n):
        self.n = n
        self.g = [[] for _ in range(n)]  # to, rev, cap
        self.pos = []

    def add_edge(self, frm, to, cap):
        """ frmからtoへ容量cap, 流量0の辺を追加, 何番目の辺かを返す"""
        m = len(self.pos)
        self.pos.append((frm, len(self.g[frm])))
        self.g[frm].append([to, len(self.g[to]), cap])
        self.g[to].append([frm, len(self.g[frm]) - 1, 0])
        return m

    def __get_edge(self, i):
        e_to, e_rev, e_cap = self.g[self.pos[i][0]][self.pos[i][1]]
        re_to, _, re_cap = self.g[e_to][e_rev]
        # from, to, cap, flow
        return (re_to, e_to, e_cap + re_cap, re_cap)

    def edges(self):
        """ 辺の情報を返す(frm, to, cap, flow) """
        m = len(self.pos)
        for i in range(m):
            yield self.__get_edge(i)

    def change_edge(self, i, new_cap, new_flow):
        """ i番目に追加された辺の容量,流量をnew_cap, new_flowに変更する """
        f, s = self.pos[i]
        rf, rs, _ = self.g[f][s]
        self.g[f][s][2] = new_cap - new_flow
        self.g[rf][rs][2] = new_flow
        return

    def __dfs(self, s, v, up):
        if v == s:
            return up
        res = 0
        level_v = self.level[v]
        for i in range(self.iter[v], len(self.g[v])):
            u_to, u_rev, _ = self.g[v][i]
            if level_v <= self.level[u_to] or self.g[u_to][u_rev][2] == 0:
                continue
            d = self.__dfs(s, u_to, min(up - res, self.g[u_to][u_rev][2]))
            if d <= 0:
                continue
            self.g[v][i][2] += d
            self.g[u_to][u_rev][2] -= d
            res += d
            if res == up:
                break
        return res

    def flow(self, s, t, flow_limit=10**18):
        """ sからtへflow_limitだけ流す。流せた量を返す """
        self.iter = [0] * self.n
        flow = 0
        while flow < flow_limit:
            self.level = [-1] * self.n
            self.level[s] = 0
            que = deque([s])
            while que:
                v = que.popleft()
                for u_to, _, u_cap in self.g[v]:
                    if u_cap == 0 or self.level[u_to] >= 0:
                        continue
                    self.level[u_to] = self.level[v] + 1
                    if u_to == t:
                        break
                    que.append(u_to)

            if self.level[t] == -1:
                break
            self.iter = [0] * self.n
            while flow < flow_limit:
                f = self.__dfs(s, t, flow_limit - flow)
                if not f:
                    break
                flow += f
        return flow

    def min_cut(self, s):
        """ 最小カットを返す。sから到達可能だとTrue """
        visited = [False] * self.n
        que = deque([s])
        while que:
            v = que.popleft()
            visited[v] = True
            for u_to, _, u_cap in self.g[v]:
                if u_cap and (not visited[u_to]):
                    visited[u_to] = True
                    que.append(u_to)
        return visited


H, W = map(int, input().split())
A = tuple(tuple(map(int, input().split())) for _ in range(H))
R = tuple(map(int, input().split()))
C = tuple(map(int, input().split()))

g = MF_graph(H * W + H + W + 2)
source = H * W + H + W
sink = source + 1
for i in range(H):
    for j in range(W):
        v = i * W + j
        row = H * W + i
        col = H * W + H + j
        g.add_edge(source, v, A[i][j])
        g.add_edge(v, row, inf)
        g.add_edge(v, col, inf)
for i, r in enumerate(R):
    row = H * W + i
    g.add_edge(row, sink, r)
for j, c in enumerate(C):
    col = H * W + H + j
    g.add_edge(col, sink, c)

ans = sum(R) + sum(C) - g.flow(source, sink)
print(ans)
0