結果

問題 No.957 植林
ユーザー akakimidoriakakimidori
提出日時 2020-02-13 20:30:24
言語 Rust
(1.77.0)
結果
RE  
実行時間 -
コード長 7,875 bytes
コンパイル時間 2,065 ms
コンパイル使用メモリ 170,624 KB
実行使用メモリ 21,060 KB
最終ジャッジ日時 2024-04-15 23:19:58
合計ジャッジ時間 6,368 ms
ジャッジサーバーID
(参考情報)
judge1 / judge3
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1 ms
5,248 KB
testcase_01 AC 1 ms
5,376 KB
testcase_02 AC 1 ms
5,376 KB
testcase_03 RE -
testcase_04 RE -
testcase_05 RE -
testcase_06 RE -
testcase_07 RE -
testcase_08 RE -
testcase_09 RE -
testcase_10 RE -
testcase_11 RE -
testcase_12 RE -
testcase_13 RE -
testcase_14 RE -
testcase_15 RE -
testcase_16 RE -
testcase_17 RE -
testcase_18 RE -
testcase_19 RE -
testcase_20 RE -
testcase_21 RE -
testcase_22 RE -
testcase_23 RE -
testcase_24 RE -
testcase_25 RE -
testcase_26 RE -
testcase_27 RE -
testcase_28 RE -
testcase_29 RE -
testcase_30 RE -
testcase_31 RE -
testcase_32 RE -
testcase_33 RE -
testcase_34 RE -
testcase_35 RE -
testcase_36 RE -
testcase_37 RE -
testcase_38 RE -
testcase_39 RE -
testcase_40 RE -
testcase_41 AC 61 ms
12,840 KB
testcase_42 AC 60 ms
12,844 KB
testcase_43 AC 66 ms
16,056 KB
testcase_44 AC 80 ms
21,060 KB
testcase_45 AC 1 ms
5,376 KB
testcase_46 AC 1 ms
5,376 KB
testcase_47 AC 1 ms
5,376 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

// https://cp-algorithms.com/graph/mpm.html

use std::cmp::*;

type FlowType = i64;

struct MPMGraph {
    size: usize,
    edge: Vec<(usize, usize, FlowType)>,
}

impl MPMGraph {
    pub fn new(size: usize) -> Self {
        MPMGraph {
            size: size,
            edge: vec![],
        }
    }
    fn add_edge(&mut self, src: usize, dst: usize, capa: FlowType) {
        assert!(src < self.size && dst < self.size);
        if src != dst {
            self.edge.push((src, dst, capa));
            self.edge.push((dst, src, 0));
        }
    }
    fn flow(&mut self, src: usize, dst: usize) -> FlowType {
        // 多重辺のマージ
        self.edge.sort();
        self.edge.dedup_by(|a, b| {
            if a.0 == b.0 && a.1 == b.1 {
                b.2 += a.2;
                true
            } else {
                false
            }
        });
        // 逆辺への参照を取得
        let mut edge = Vec::with_capacity(self.edge.len());
        for &(s, t, c) in self.edge.iter() {
            let k = self.edge.binary_search_by(|e| (e.0, e.1).cmp(&(t, s))).unwrap();
            edge.push((s, t, c, k));
        }
        // フローが流れなくなるまでループ
        let mut ans = 0;
        loop {
            // 到達可能性を確かめる
            let mut graph = vec![vec![]; self.size];
            let mut inv_graph = vec![vec![]; self.size];
            for &(s, t, c, _) in edge.iter() {
                if c > 0 {
                    graph[s].push(t);
                    inv_graph[t].push(s);
                }
            }
            let depth = MPMGraph::bfs(src, dst, &graph);
            // 到達不能
            if depth[dst] >= self.size {
                break;
            }
            let inv_depth = MPMGraph::bfs(dst, src, &inv_graph);
            // depth, inv_depthから使用される可能性のある辺のみからなるグラフを構築
            // pin, pout は流入、流出
            let mut flow_graph = vec![vec![]; self.size];
            let mut inv_flow_graph = vec![vec![]; self.size];
            let mut pin = vec![0; self.size];
            let mut pout = vec![0; self.size];
            for (i, &(s, t, c, _)) in edge.iter().enumerate() {
                if c > 0 && depth[s] + 1 == depth[t] && inv_depth[t] + 1 == inv_depth[s] {
                    flow_graph[s].push((t, i));
                    pout[s] += c;
                    pin[t] += c;
                    inv_flow_graph[t].push((s, i));
                }
            }
            // src, dstは適当に初期化
            let inf = 1_000_000_000_000_000_000i64;
            pout[src] = inf;
            pin[src] = inf;
            pout[dst] = inf;
            pin[dst] = inf;
            // 採用されたか
            let mut alive = vec![true; self.size];
            alive[src] = false;
            alive[dst] = false;
            // どこまでみたかのアレ
            let mut it = vec![0; self.size];
            let mut inv_it = vec![0; self.size];
            loop {
                // ポテンシャルが最小のものを検索
                let mut v = (pout[src], src);
                for (u, (pin, (pout, alive))) in pin.iter().zip(pout.iter().zip(alive.iter())).enumerate() {
                    let pot = min(*pin, *pout);
                    if *alive && pot < v.0 {
                        v = (pot, u);
                    }
                }
                // 存在しないならbreak
                if v.1 == src {
                    break;
                }
                alive[v.1] = false;
                if v.0 == 0 {
                    MPMGraph::remove_node(v.1, &flow_graph, &inv_flow_graph, &mut edge, &mut pin, &mut pout);
                    continue;
                }
                ans += v.0;
                MPMGraph::push(v.1, dst, v.0, &flow_graph, &mut edge, &mut it, &mut pin, &mut pout);
                MPMGraph::push(v.1, src, v.0, &inv_flow_graph, &mut edge, &mut inv_it, &mut pout, &mut pin);
                MPMGraph::remove_node(v.1, &flow_graph, &inv_flow_graph, &mut edge, &mut pin, &mut pout);
            }
        }
        ans
    }
    fn push(src: usize, dst: usize, flow: FlowType, graph: &[Vec<(usize, usize)>], edge: &mut [(usize, usize, FlowType, usize)], it: &mut [usize], pin: &mut [FlowType], pout: &mut [FlowType]) {
        let mut q = std::collections::VecDeque::new();
        let mut assign = vec![0; graph.len()];
        assign[src] = flow;
        q.push_back(src);
        while let Some(v) = q.pop_front() {
            assert!(assign[v] > 0);
            assert!(pout[v] >= assign[v]);
            if v == dst {
                break;
            }
            let mut f = assign[v];
            for &(u, k) in graph[v][it[v]..].iter() {
                let capa = min(pout[u], pin[u]);
                if capa > 0 && assign[u] == 0 {
                    q.push_back(u);
                }
                if capa >= f {
                    edge[k].2 -= f;
                    edge[edge[k].3].2 += f;
                    pout[v] -= f;
                    pin[u] -= f;
                    assign[u] += f;
                    f = 0;
                    break;
                }
                edge[k].2 -= capa;
                edge[edge[k].3].2 += capa;
                pout[v] -= capa;
                pin[u] -= capa;
                assign[u] += capa;
                f -= capa;
                it[v] += 1;
            }
            assert!(f == 0);
        }
        assert!(assign[dst] == flow);
    }
    fn remove_node(v: usize, graph: &[Vec<(usize, usize)>], inv_graph: &[Vec<(usize, usize)>], edge: &mut [(usize, usize, FlowType, usize)], pin: &mut [FlowType], pout: &mut [FlowType]) {
        for &(u, k) in graph[v].iter() {
            let capa = edge[k].2;
            pin[u] -= capa;
            pout[v] -= capa;
        }
        for &(u, k) in inv_graph[v].iter() {
            let capa = edge[k].2;
            pout[u] -= capa;
            pin[v] -= capa;
        }
    }
    fn bfs(src: usize, dst: usize, graph: &[Vec<usize>]) -> Vec<usize> {
        let mut depth = vec![graph.len(); graph.len()];
        depth[src] = 0;
        let mut q = std::collections::VecDeque::new();
        q.push_back(src);
        'outer: while let Some(v) = q.pop_front() {
            for &u in graph[v].iter() {
                if depth[u] > depth[v] + 1 {
                    depth[u] = depth[v] + 1;
                    if u == dst {
                        break 'outer;
                    }
                    q.push_back(u);
                }
            }
        }
        depth
    }
}

fn run() {
    use std::io::Read;
    let mut s = String::new();
    std::io::stdin().read_to_string(&mut s).unwrap();
    let mut it = s.trim().split_whitespace();
    let h: usize = it.next().unwrap().parse().unwrap();
    let w: usize = it.next().unwrap().parse().unwrap();
    let a: Vec<Vec<i64>> = (0..h).map(|_| (0..w).map(|_| it.next().unwrap().parse().unwrap()).collect()).collect();
    let r: Vec<i64> = (0..h).map(|_| it.next().unwrap().parse().unwrap()).collect();
    let c: Vec<i64> = (0..w).map(|_| it.next().unwrap().parse().unwrap()).collect();
    let mut graph = MPMGraph::new(h + w + 2);
    let src = h + w;
    let dst = src + 1;
    for (i, a) in a.iter().enumerate() {
        let mut local = 0;
        for (j, a) in a.iter().enumerate() {
            graph.add_edge(h + j, i, *a);
            local += *a;
        }
        graph.add_edge(i, dst, local);
    }
    let mut sum = 0;
    for (i, r) in r.iter().enumerate() {
        sum += *r;
        graph.add_edge(src, i, *r);
    }
    for (i, c) in c.iter().enumerate() {
        sum += *c;
        graph.add_edge(src, i + h, *c);
    }
    let ans = sum - graph.flow(src, dst);
    println!("{}", ans);
}

fn main() {
    run();
}
0