結果

問題 No.3509 Get More Money
コンテスト
ユーザー rhoo
提出日時 2026-03-16 18:41:12
言語 Rust
(1.94.0 + proconio + num + itertools)
コンパイル:
/usr/bin/rustc_custom
実行:
./target/release/main
結果
TLE  
実行時間 -
コード長 11,172 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 1,793 ms
コンパイル使用メモリ 200,112 KB
実行使用メモリ 81,456 KB
最終ジャッジ日時 2026-04-17 19:38:34
合計ジャッジ時間 15,948 ms
ジャッジサーバーID
(参考情報)
judge1_1 / judge2_1
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample -- * 1
other TLE * 1 -- * 59
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#![allow(non_snake_case,dead_code)]



fn main(){
    proconio::input!{
        t:usize,
    }
    for _ in 0..t{
        solve();
    }
}



fn solve(){
    proconio::input!{
        n:usize,
        k:i64,
        a:[i64;n],
        b:[i64;n],
        c:[i64;n],
        d:[i64;n],
    }

    let mut g=NetworkSimplex::new(n+2);
    let source=n;
    let sink=n+1;
    
    for i in 0..n{
        g.add_edge(source,i,0,b[i],a[i]);
        g.add_edge(i,sink,0,d[i],-c[i]);
        
        if 0<i{
            g.add_edge(i-1,i,0,k,0);
        }
    }

    let flow=b.iter().sum::<i64>();
    g.add_edge(source,sink,0,flow,0);

    g.add_excess(source,flow);
    g.add_excess(sink,-flow);
    let res=network_simplex(g);

    println!("{}",-res.cost);
}



// https://github.com/yosupo06/yosupo-library/blob/main/src/yosupo/networksimplex.hpp ここからパクりました
// 負辺ok
mod network_simplex{
    #[derive(Clone,Copy,Debug)]
    struct Edge{
        to:usize,
        cap:i64,
        cost:i64,
    }

    pub struct NetworkSimplex{
        n:usize,
        edges:Vec<Edge>,
        lowers:Vec<i64>,
        excess:Vec<i64>,
    }
    impl NetworkSimplex{
        pub fn new(n:usize)->Self{
            Self{
                n,
                edges:vec![],
                lowers:vec![],
                excess:vec![0;n],
            }
        }

        pub fn add_excess(&mut self,v:usize,ex:i64){
            self.excess[v]+=ex;
        }

        pub fn add_edge(&mut self,u:usize,v:usize,lower:i64,upper:i64,cost:i64){
            let new=Edge{to:v,cap:upper-lower,cost};
            self.edges.push(new);
            let new=Edge{to:u,cap:0,cost:-cost};
            self.edges.push(new);
            self.excess[u]-=lower;
            self.excess[v]+=lower;
            self.lowers.push(lower);
        }
    }

    pub struct FlowResult{
        pub feasible:bool,
        pub cost:i128,
        pub flow:Vec<i64>,
        pub pot:Vec<i64>,
    }

    #[derive(Clone,Copy)]
    struct Parent{
        p:usize,
        e:usize,
        up:i64,
        down:i64,
    }

    pub fn network_simplex(g:NetworkSimplex)->FlowResult{
        let mut edges=g.edges;
        let excess=g.excess;
        let n=g.n;
        let m=edges.len();
        
        let mut pot=vec![0;n+1];
        let mut art_cost=1;
        for i in (0..m).step_by(2){
            art_cost+=edges[i].cost.abs();
        }

        let mut parents=vec![Parent{p:0,e:0,up:0,down:0};n];

        for i in 0..n{
            if excess[i]>=0{
                edges.push(Edge{to:n,cap:0,cost:art_cost});
                edges.push(Edge{to:i,cap:excess[i],cost:-art_cost});
                pot[i]=-art_cost;
            } else{
                edges.push(Edge{to:n,cap:-excess[i],cost:-art_cost});
                edges.push(Edge{to:i,cap:0,cost:art_cost});
                pot[i]=art_cost;
            }
            parents[i].p=n;
            parents[i].e=edges.len()-2;
            parents[i].up=edges[parents[i].e].cap;
            parents[i].down=edges[parents[i].e^1].cap;
        }

        let mut depth=vec![1;n+1];
        depth[n]=0;

        let mut next=vec![0;2*(n+1)];
        let mut prev=vec![0;2*(n+1)];

        let conn=|a:usize,b:usize,next_vec:&mut [usize],prev_vec:&mut [usize]|{
            next_vec[a]=b;
            prev_vec[b]=a;
        };

        for i in 0..=n{
            conn(2*i,2*i+1,&mut next,&mut prev);
        }
        for i in 0..n{
            let n_2n=next[2*n];
            conn(2*i+1,n_2n,&mut next,&mut prev);
            conn(2*n,2*i,&mut next,&mut prev);
        }

        fn push_flow(ei0:usize,edges:&mut [Edge],pot:&mut [i64],parents:&mut [Parent],depth:&mut [i32],next:&mut [usize],prev:&mut [usize]){
            let u0=edges[ei0^1].to;
            let v0=edges[ei0].to;
            let cycle_len=edges[ei0].cost+pot[u0]-pot[v0];

            let mut flow=edges[ei0].cap;
            let mut del_u_side=true;
            let mut del_u=v0;

            let lca={
                let u=u0;
                let v=v0;
                
                let mut u_curr=u;
                let mut v_curr=v;
                
                while depth[u_curr]>depth[v_curr]{
                    if parents[u_curr].down<flow{
                        flow=parents[u_curr].down;
                        del_u=u_curr;
                        del_u_side=true;
                    }
                    u_curr=parents[u_curr].p;
                }
                while depth[v_curr]>depth[u_curr]{
                    if parents[v_curr].up<=flow{
                        flow=parents[v_curr].up;
                        del_u=v_curr;
                        del_u_side=false;
                    }
                    v_curr=parents[v_curr].p;
                }
                
                while u_curr!=v_curr{
                    if parents[u_curr].down<flow{
                        flow=parents[u_curr].down;
                        del_u=u_curr;
                        del_u_side=true;
                    }
                    u_curr=parents[u_curr].p;

                    if parents[v_curr].up<=flow{
                        flow=parents[v_curr].up;
                        del_u=v_curr;
                        del_u_side=false;
                    }
                    v_curr=parents[v_curr].p;
                }
                u_curr
            };

            if flow>0{
                let mut u=u0;
                while u!=lca{
                    parents[u].up+=flow;
                    parents[u].down-=flow;
                    u=parents[u].p;
                }
                let mut v=v0;
                while v!=lca{
                    parents[v].up-=flow;
                    parents[v].down+=flow;
                    v=parents[v].p;
                }
            }

            let mut u=u0;
            let mut par=v0;
            let mut p_diff=-cycle_len;
            let mut p_caps_first=edges[ei0].cap-flow;
            let mut p_caps_second=edges[ei0^1].cap+flow;

            if !del_u_side{
                std::mem::swap(&mut u,&mut par);
                std::mem::swap(&mut p_caps_first,&mut p_caps_second);
                p_diff*=-1;
            }
            let mut par_e=ei0^(!del_u_side) as usize;

            while par!=del_u{
                let mut d=depth[par];
                let mut idx=2*u;
                while idx!=2*u+1{
                    if idx%2==0{
                        d+=1;
                        let node_idx=idx/2;
                        pot[node_idx]+=p_diff;
                        depth[node_idx]=d;
                    } else{
                        d-=1;
                    }
                    idx=next[idx];
                }

                let prev_2u=prev[2*u];
                let next_2u1=next[2*u+1];
                next[prev_2u]=next_2u1;
                prev[next_2u1]=prev_2u;

                let next_2par=next[2*par];
                next[2*u+1]=next_2par;
                prev[next_2par]=2*u+1;

                next[2*par]=2*u;
                prev[2*u]=2*par;

                std::mem::swap(&mut parents[u].e,&mut par_e);
                par_e^=1;

                std::mem::swap(&mut parents[u].up,&mut p_caps_first);
                std::mem::swap(&mut parents[u].down,&mut p_caps_second);
                std::mem::swap(&mut p_caps_first,&mut p_caps_second);

                let next_u=parents[u].p;
                parents[u].p=par;
                par=u;
                u=next_u;
            }
            edges[par_e].cap=p_caps_first;
            edges[par_e^1].cap=p_caps_second;
        }

        // Pivot Rule constants
        let list_length=10.max((0.2*(m as f64).sqrt()).round() as usize);
        let minor_limit=3.max((0.1*(list_length as f64)).round() as usize);
        let mut candidates=Vec::with_capacity(list_length);

        let mut ei=0;
        loop{
            for _ in 0..minor_limit{
                if candidates.is_empty(){
                    break;
                }
                let mut best=0;
                let mut best_ei=!0;

                let mut i=0;
                while i<candidates.len(){
                    let cei:usize=candidates[i];
                    if edges[cei].cap==0{
                        let last=candidates.len()-1;
                        candidates.swap(i,last);
                        candidates.pop();
                        continue;
                    }
                    let c_len=edges[cei].cost+pot[edges[cei^1].to]-pot[edges[cei].to];
                    if c_len>=0{
                        let last=candidates.len()-1;
                        candidates.swap(i,last);
                        candidates.pop();
                        continue;
                    }

                    if c_len<best{
                        best=c_len;
                        best_ei=cei;
                    }
                    i+=1;
                }

                if best_ei==!0{
                    break;
                }
                push_flow(best_ei,&mut edges,&mut pot,&mut parents,&mut depth,&mut next,&mut prev);
            }

            let mut best=0;
            let mut best_ei=!0;

            candidates.clear();
            let edges_len=edges.len();
            for _ in 0..edges_len{
                if edges[ei].cap>0{
                    let clen=edges[ei].cost+pot[edges[ei^1].to]-pot[edges[ei].to];
                    if clen<0{
                        if clen<best{
                            best=clen;
                            best_ei=ei;
                        }
                        candidates.push(ei);
                        if candidates.len()==list_length{
                            break;
                        }
                    }
                }

                ei+=1;
                if ei==edges_len{
                    ei=0;
                }
            }

            if candidates.is_empty(){
                break;
            }
            push_flow(best_ei,&mut edges,&mut pot,&mut parents,&mut depth,&mut next,&mut prev);
        }

        // Finalize
        for i in 0..n{
            edges[parents[i].e].cap=parents[i].up;
            edges[parents[i].e^1].cap=parents[i].down;
        }

        let mut feasible=true;
        for i in 0..n{
            if excess[i]>=0{
                if edges[m+2*i+1].cap>0{
                    feasible=false;
                    break;
                }
            } else{
                if edges[m+2*i].cap>0{
                    feasible=false;
                    break;
                }
            }
        }

        if !feasible{
            return FlowResult{feasible:false,cost:0,flow:vec![],pot:vec![]};
        }

        let mut total_cost=0;
        let mut flow=Vec::with_capacity(m/2);
        for i in (0..m).step_by(2){
            let f=g.lowers[i/2]+edges[i^1].cap;
            flow.push(f);
            total_cost+=f as i128*edges[i].cost as i128;
        }
        pot.pop();

        FlowResult{
            feasible:true,
            cost:total_cost,
            flow,pot,
        }
    }
}
use network_simplex::*;
0