#ifndef INCLUDE_MODE #define INCLUDE_MODE // #define REACTIVE // #define USE_GETLINE #endif #ifdef INCLUDE_MAIN inline void Solve() { CIN( int , K , N , M ); CIN_A( int , A , K ); CIN_A( int , B , N ); Map A_hind{}; FOR( k , 0 , K ){ A_hind[A[k]]++; } using path_type = tuple; gE.resize( N + 2 ); FOR_ITR( A_hind ){ gE[0].push_back( { itr->first , 0 , itr->second } ); } FOREQ( i , 1 , N ){ gE[i].push_back( { N + 1 , 0 , B[i-1] } ); } FOR( j , 0 , M ){ CIN( ll , uj , vj , wj ); gE[uj].push_back( { vj , wj , K } ); gE[vj].push_back( { uj , wj , K } ); } Graph graph{ N + 2 , Get( gE ) }; // MinimalCostFlow mcf{ move( graph ) , 1LL , 1LL<<62 }; AbstractMinimalCostFlow mcf{ move( graph ) , Ring( 1LL ) , 1LL<<62 }; auto [answer,flow] = mcf.GetFlow( 0 , N + 1 , K ); RETURN( answer ); } REPEAT_MAIN(1); #else // INCLUDE_MAIN #ifdef INCLUDE_SUB // グラフ用 template Map gF; template vector gA; template vector> gE; template typename V> inline auto Get( const V& a ) { return [&]( const int& i ){ return a[i]; }; } // 圧縮時は中身だけ削除する。 inline void Experiment() { } // 圧縮時は中身だけ削除する。 inline void SmallTest() { } #define INCLUDE_MAIN #include __FILE__ #else // INCLUDE_SUB #ifdef INCLUDE_LIBRARY /* C-x 3 C-x o C-x C-fによるファイル操作用 BFS: c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/BreadthFirstSearch/compress.txt CoordinateCompress: c:/Users/user/Documents/Programming/Mathematics/SetTheory/DirectProduct/CoordinateCompress/compress.txt DFSOnTree c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/DepthFirstSearch/Tree/a.hpp Divisor: c:/Users/user/Documents/Programming/Mathematics/Arithmetic/Prime/Divisor/compress.txt Polynomial c:/Users/user/Documents/Programming/Mathematics/Polynomial/compress.txt UnionFind c:/Users/user/Documents/Programming/Mathematics/Geometry/Graph/UnionFindForest/compress.txt */ // VVV 常設でないライブラリは以下に挿入する。 template class VirtualPointedSet { public: virtual const U& Point() const noexcept = 0; inline const U& Unit() const noexcept; inline const U& Zero() const noexcept; inline const U& One() const noexcept; inline const U& Infty() const noexcept; inline const U& size() const noexcept; }; template class PointedSet : virtual public VirtualPointedSet { private: U m_b_U; public: inline PointedSet( const U& b_u = U() ); inline const U& Point() const noexcept; }; template class VirtualNSet { public: virtual U Transfer( const U& u ) = 0; inline U Inverse( const U& u ); }; template class AbstractNSet : virtual public VirtualNSet { private: F_U m_f_U; public: inline AbstractNSet( F_U f_U ); inline U Transfer( const U& u ); }; template class VirtualMagma { public: virtual U Product( const U& u0 , const U& u1 ) = 0; inline U Sum( const U& u0 , const U& u1 ); }; template class AbstractMagma : virtual public VirtualMagma { private: M_U m_m_U; public: inline AbstractMagma( M_U m_U ); inline U Product( const U& u0 , const U& u1 ); }; template inline PointedSet::PointedSet( const U& b_U ) : m_b_U( b_U ) {} template inline const U& PointedSet::Point() const noexcept { return m_b_U; } template inline const U& VirtualPointedSet::Unit() const noexcept { return Point(); } template inline const U& VirtualPointedSet::Zero() const noexcept { return Point(); } template inline const U& VirtualPointedSet::One() const noexcept { return Point(); } template inline const U& VirtualPointedSet::Infty() const noexcept { return Point(); } template inline const U& VirtualPointedSet::size() const noexcept { return Point(); } template inline AbstractNSet::AbstractNSet( F_U f_U ) : m_f_U( move( f_U ) ) { static_assert( is_invocable_r_v ); } template inline U AbstractNSet::Transfer( const U& u ) { return m_f_U( u ); } template inline U VirtualNSet::Inverse( const U& u ) { return Transfer( u ); } template inline AbstractMagma::AbstractMagma( M_U m_U ) : m_m_U( move( m_U ) ) { static_assert( is_invocable_r_v ); } template inline U AbstractMagma::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); } template inline U VirtualMagma::Sum( const U& u0 , const U& u1 ) { return Product( u0 , u1 ); } template class VirtualMonoid : virtual public VirtualMagma , virtual public VirtualPointedSet {}; template class AdditiveMonoid : virtual public VirtualMonoid , public PointedSet { public: inline U Product( const U& u0 , const U& u1 ); }; template class MultiplicativeMonoid : virtual public VirtualMonoid , public PointedSet { public: inline MultiplicativeMonoid( const U& e_U ); inline U Product( const U& u0 , const U& u1 ); }; template class AbstractMonoid : virtual public VirtualMonoid , public AbstractMagma , public PointedSet { public: inline AbstractMonoid( M_U m_U , const U& e_U ); inline U Product( const U& u0 , const U& u1 ); }; template inline MultiplicativeMonoid::MultiplicativeMonoid( const U& e_U ) : PointedSet( e_U ) {} template inline AbstractMonoid::AbstractMonoid( M_U m_U , const U& e_U ) : AbstractMagma( move( m_U ) ) , PointedSet( e_U ) {} template inline U AdditiveMonoid::Product( const U& u0 , const U& u1 ) { return u0 + u1; } template inline U MultiplicativeMonoid::Product( const U& u0 , const U& u1 ) { return u0 * u1; } template inline U AbstractMonoid::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); } template class VirtualGroup : virtual public VirtualMonoid , virtual public VirtualPointedSet , virtual public VirtualNSet {}; template class AdditiveGroup : virtual public VirtualGroup , public AdditiveMonoid { public: inline U Transfer( const U& u ); }; template class AbstractGroup : virtual public VirtualGroup , public AbstractMonoid , public AbstractNSet { public: inline AbstractGroup( M_U m_U , const U& e_U , I_U i_U ); inline U Transfer( const U& u ); }; template inline AbstractGroup::AbstractGroup( M_U m_U , const U& e_U , I_U i_U ) : AbstractMonoid( move( m_U ) , e_U ) , AbstractNSet( move( i_U ) ) {} template inline U AbstractGroup::Transfer( const U& u ) { return m_i_U( u ); } template inline U AdditiveGroup::Transfer( const U& u ) { return -u; } template class VirtualRing { private: GROUP m_R0; MONOID m_R1; protected: inline VirtualRing( GROUP R0 , MONOID R1 ); public: inline U Sum( const U& u0 , const U& u1 ); inline const U& Zero() const noexcept; inline U Inverse( const U& u ); inline U Product( const U& u0 , const U& u1 ); inline const U& One() const noexcept; inline GROUP& AdditiveGroup() noexcept; inline MONOID& MultiplicativeMonoid() noexcept; }; template class Ring : virtual public VirtualRing,MultiplicativeMonoid> { public: inline Ring( const U& one_U ); }; template class AbstractRing : virtual public VirtualRing,AbstractMonoid> { public: inline AbstractRing( A_U a_U , const U& z_U , I_U i_U , M_U m_U , const U& e_U ); }; template inline VirtualRing::VirtualRing( GROUP R0 , MONOID R1 ) : m_R0( move( R0 ) ) , m_R1( move( R1 ) ) {} template inline Ring::Ring( const U& one_U ) : VirtualRing,MultiplicativeMonoid>( AdditiveGroup() , MultiplicativeMonoid( one_U ) ) {} template inline AbstractRing::AbstractRing( A_U a_U , const U& z_U , I_U i_U , M_U m_U , const U& e_U ) : VirtualRing,AbstractMonoid>( AbstractGroup( move( a_U ) , z_U , move( i_U ) ) , AbstractMonoid( move( m_U ) , e_U ) ) {} template inline U VirtualRing::Sum( const U& u0 , const U& u1 ) { return m_R0.Sum( u0 , u1 ); } template inline const U& VirtualRing::Zero() const noexcept { return m_R0.Zero(); } template inline U VirtualRing::Inverse( const U& u ) { return m_R0.Inverse( u ); } template inline U VirtualRing::Product( const U& u0 , const U& u1 ) { return m_R1.Product( u0 , u1 ); } template inline const U& VirtualRing::One() const noexcept { return m_R1.One(); } template inline GROUP& VirtualRing::AdditiveGroup() noexcept { return m_R0; } template inline MONOID& VirtualRing::MultiplicativeMonoid() noexcept { return m_R1; } #ifndef RET_TYPE #define RET_TYPE template using ret_t = decltype( declval()( declval()... ) ); #endif #ifndef INNER_TYPE #define INNER_TYPE template using inner_t = typename T::type; #endif #ifndef decldecay_t #define decldecay_t( VAR ) decay_t #endif // Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nは互いに逆写像である仮想関数。 template class VirtualGraph : public PointedSet { private: E m_edge; public: inline VirtualGraph( const int& size , E edge ); virtual R1 Enumeration( const int& i ) = 0; virtual R2 Enumeration_inv( const T& t ) = 0; inline void Reset(); ret_t Edge( const T& t ); using type = T; }; template class Graph : virtual public VirtualGraph { public: inline Graph( const int& size , E edge ); inline const int& Enumeration( const int& i ); inline const int& Enumeration_inv( const int& t ); template inline Graph GetGraph( F edge ) const; }; template class EnumerationGraph : virtual public VirtualGraph,ret_t,E> { private: Enum_T m_enum_T; Enum_T_inv m_enum_T_inv; public: inline EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ); inline ret_t Enumeration( const int& i ); inline ret_t Enumeration_inv( const T& t ); template inline EnumerationGraph GetGraph( F edge ) const; }; template EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) -> EnumerationGraph(declval()(0).back())),Enum_T,Enum_T_inv,E>; // 推論補助のためにE::operator()はデフォルト引数が必要。 template class MemorisationGraph : virtual public VirtualGraph { private: int m_length; vector m_memory; Map m_memory_inv; public: inline MemorisationGraph( const int& size , E edge ); // push_backする可能性のあるvectorなので参照にしないように注意 inline T Enumeration( const int& i ); inline const int& Enumeration_inv( const T& t ); inline void Reset(); template inline MemorisationGraph GetGraph( F edge ) const; }; template MemorisationGraph( const int& size , E edge ) -> MemorisationGraph(declval()().back())),E>; template inline VirtualGraph::VirtualGraph( const int& size , E edge ) : PointedSet( size ) , m_edge( move( edge ) ) { static_assert( is_constructible_v && is_constructible_v && is_invocable_v ); } template inline Graph::Graph( const int& size , E edge ) : VirtualGraph( size , move( edge ) ) {} template inline EnumerationGraph::EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) : VirtualGraph,ret_t,E>( size , move( edge ) ) , m_enum_T( move( enum_T ) ) , m_enum_T_inv( move( enum_T_inv ) ) {} template inline MemorisationGraph::MemorisationGraph( const int& size , E edge ) : VirtualGraph( size , move( edge ) ) , m_length() , m_memory() , m_memory_inv() {} template inline ret_t VirtualGraph::Edge( const T& t ) { return m_edge( t ); } template inline const int& Graph::Enumeration( const int& i ) { return i; } template inline ret_t EnumerationGraph::Enumeration( const int& i ) { return m_enum_T( i ); } template inline T MemorisationGraph::Enumeration( const int& i ) { assert( 0 <= i && i < m_length ); return m_memory[i]; } template inline const int& Graph::Enumeration_inv( const int& i ) { return i; } template inline ret_t EnumerationGraph::Enumeration_inv( const T& t ) { return m_enum_T_inv( t ); } template inline const int& MemorisationGraph::Enumeration_inv( const T& t ) { if( m_memory_inv.count( t ) == 0 ){ assert( m_length < this->size() ); m_memory.push_back( t ); return m_memory_inv[t] = m_length++; } return m_memory_inv[t]; } template void VirtualGraph::Reset() {} template inline void MemorisationGraph::Reset() { m_length = 0; m_memory.clear(); m_memory_inv.clear(); } template template inline Graph Graph::GetGraph( F edge ) const { return Graph( this->size() , move( edge ) ); } template template inline EnumerationGraph EnumerationGraph::GetGraph( F edge ) const { return EnumerationGraph( this->size() , m_enum_T , m_enum_T_inv , move( edge ) ); } template template inline MemorisationGraph MemorisationGraph::GetGraph( F edge ) const { return MemorisationGraph( this->size() , move( edge ) ); } #define BELLMAN_FORD_BODY( INITIALISE_PREV , SET_PREV ) \ const U& zero = m_M.Zero(); \ const U& infty = this->Infty(); \ assert( zero < infty ); \ const int& size = m_G.size(); \ auto&& i_start = m_G.Enumeration_inv( t_start ); \ assert( 0 <= i_start && i_start < size ); \ vector found( size ); \ vector weight( size , infty ); \ found[i_start] = true; \ weight[i_start] = 0; \ INITIALISE_PREV; \ \ for( int length = 0 ; length < size ; length++ ){ \ \ for( int i = 0 ; i < size ; i++ ){ \ \ if( found[i] ){ \ \ const U& weight_i = weight[i]; \ assert( weight_i != infty ); \ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); \ \ for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \ \ auto&& j = m_G.Enumeration_inv( itr->first ); \ const U& edge_ij = itr->second; \ U temp = m_M.Sum( weight_i , edge_ij ); \ U& weight_j = weight[j]; \ \ if( weight_j > temp ){ \ \ found[j] = true; \ weight_j = move( temp ); \ SET_PREV; \ \ } \ \ } \ \ } \ \ } \ \ } \ \ bool valid = true; \ \ for( int i = 0 ; i < size && valid ; i++ ){ \ \ if( found[i] ){ \ \ const U& weight_i = weight[i]; \ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); \ \ for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \ \ auto&& j = m_G.Enumeration_inv( itr->first ); \ const U& edge_ij = itr->second; \ U& weight_j = weight[j]; \ const U temp = m_M.Sum( weight_i , edge_ij ); \ \ if( weight_j > temp ){ \ \ valid = false; \ break; \ \ } \ \ } \ \ } \ \ } \ // GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。 // 入力の範囲内で要件 // (0) Mは全順序可換モノイド構造である。 // (1) inftyがE_Gの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。 // が成り立つ場合にのみサポート。 // 単一始点全終点最短経路探索/経路復元なしO(|V_G| |E_G|) // 単一始点全終点最短経路探索/経路復元ありO(|V_G| |E_G|) template class AbstractBellmanFord : public PointedSet { private: GRAPH m_G; MONOID m_M; public: inline AbstractBellmanFord( GRAPH G , MONOID M , const U& infty ); // 負の閉路が存在すればfalse、存在しなければtrueを第1成分に返す。 tuple> GetDistance( const inner_t& t_start ); template