結果
問題 | No.2604 Initial Motion |
ユーザー | 👑 p-adic |
提出日時 | 2024-01-22 14:58:06 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 1,830 ms / 3,000 ms |
コード長 | 51,349 bytes |
コンパイル時間 | 5,899 ms |
コンパイル使用メモリ | 304,696 KB |
実行使用メモリ | 5,504 KB |
最終ジャッジ日時 | 2024-09-28 06:25:47 |
合計ジャッジ時間 | 42,673 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge1 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
5,248 KB |
testcase_01 | AC | 2 ms
5,376 KB |
testcase_02 | AC | 3 ms
5,376 KB |
testcase_03 | AC | 64 ms
5,376 KB |
testcase_04 | AC | 63 ms
5,376 KB |
testcase_05 | AC | 65 ms
5,376 KB |
testcase_06 | AC | 63 ms
5,376 KB |
testcase_07 | AC | 64 ms
5,376 KB |
testcase_08 | AC | 63 ms
5,376 KB |
testcase_09 | AC | 60 ms
5,376 KB |
testcase_10 | AC | 62 ms
5,376 KB |
testcase_11 | AC | 64 ms
5,376 KB |
testcase_12 | AC | 62 ms
5,376 KB |
testcase_13 | AC | 1,554 ms
5,376 KB |
testcase_14 | AC | 1,034 ms
5,376 KB |
testcase_15 | AC | 682 ms
5,376 KB |
testcase_16 | AC | 1,397 ms
5,376 KB |
testcase_17 | AC | 1,830 ms
5,376 KB |
testcase_18 | AC | 1,747 ms
5,376 KB |
testcase_19 | AC | 1,678 ms
5,376 KB |
testcase_20 | AC | 1,353 ms
5,376 KB |
testcase_21 | AC | 1,065 ms
5,376 KB |
testcase_22 | AC | 1,683 ms
5,376 KB |
testcase_23 | AC | 1,157 ms
5,376 KB |
testcase_24 | AC | 1,483 ms
5,376 KB |
testcase_25 | AC | 1,711 ms
5,376 KB |
testcase_26 | AC | 1,295 ms
5,376 KB |
testcase_27 | AC | 893 ms
5,376 KB |
testcase_28 | AC | 1,196 ms
5,376 KB |
testcase_29 | AC | 1,539 ms
5,376 KB |
testcase_30 | AC | 970 ms
5,376 KB |
testcase_31 | AC | 1,289 ms
5,376 KB |
testcase_32 | AC | 1,179 ms
5,376 KB |
testcase_33 | AC | 6 ms
5,376 KB |
testcase_34 | AC | 1,504 ms
5,376 KB |
testcase_35 | AC | 1,679 ms
5,376 KB |
testcase_36 | AC | 1,621 ms
5,376 KB |
testcase_37 | AC | 5 ms
5,376 KB |
testcase_38 | AC | 3 ms
5,376 KB |
testcase_39 | AC | 4 ms
5,376 KB |
testcase_40 | AC | 1,504 ms
5,504 KB |
testcase_41 | AC | 1,496 ms
5,504 KB |
ソースコード
#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<int,int> A_hind{}; FOR( k , 0 , K ){ A_hind[A[k]]++; } using path_type = tuple<int,ll,ll>; gE<path_type>.resize( N + 2 ); FOR_ITR( A_hind ){ gE<path_type>[0].push_back( { itr->first , 0 , itr->second } ); } FOREQ( i , 1 , N ){ gE<path_type>[i].push_back( { N + 1 , 0 , B[i-1] } ); } FOR( j , 0 , M ){ CIN( ll , uj , vj , wj ); gE<path_type>[uj].push_back( { vj , wj , K } ); gE<path_type>[vj].push_back( { uj , wj , K } ); } Graph graph{ N + 2 , Get( gE<path_type> ) }; 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 <typename T> Map<T,T> gF; template <typename T> vector<T> gA; template <typename PATH> vector<list<PATH>> gE; template <typename T , template <typename...> typename V> inline auto Get( const V<T>& 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 常設でないライブラリは以下に挿入する。 #ifndef decldecay_t #define decldecay_t( VAR ) decay_t<decltype( VAR )> #endif template <typename U> 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 <typename U> class PointedSet : virtual public VirtualPointedSet<U> { private: U m_b_U; public: inline PointedSet( const U& b_u = U() ); inline const U& Point() const noexcept; }; template <typename U> class VirtualNSet { public: virtual U Transfer( const U& u ) = 0; inline U Inverse( const U& u ); }; template <typename U , typename F_U> class AbstractNSet : virtual public VirtualNSet<U> { private: F_U m_f_U; public: inline AbstractNSet( F_U f_U ); inline U Transfer( const U& u ); }; template <typename U> class VirtualMagma { public: virtual U Product( const U& u0 , const U& u1 ) = 0; inline U Sum( const U& u0 , const U& u1 ); }; template <typename U , typename M_U> class AbstractMagma : virtual public VirtualMagma<U> { private: M_U m_m_U; public: inline AbstractMagma( M_U m_U ); inline U Product( const U& u0 , const U& u1 ); }; template <typename U> inline PointedSet<U>::PointedSet( const U& b_U ) : m_b_U( b_U ) {} template <typename U> inline const U& PointedSet<U>::Point() const noexcept { return m_b_U; } template <typename U> inline const U& VirtualPointedSet<U>::Unit() const noexcept { return Point(); } template <typename U> inline const U& VirtualPointedSet<U>::Zero() const noexcept { return Point(); } template <typename U> inline const U& VirtualPointedSet<U>::One() const noexcept { return Point(); } template <typename U> inline const U& VirtualPointedSet<U>::Infty() const noexcept { return Point(); } template <typename U> inline const U& VirtualPointedSet<U>::size() const noexcept { return Point(); } template <typename U , typename F_U> inline AbstractNSet<U,F_U>::AbstractNSet( F_U f_U ) : m_f_U( move( f_U ) ) { static_assert( is_invocable_r_v<U,F_U,U> ); } template <typename U , typename F_U> inline U AbstractNSet<U,F_U>::Transfer( const U& u ) { return m_f_U( u ); } template <typename U> inline U VirtualNSet<U>::Inverse( const U& u ) { return Transfer( u ); } template <typename U , typename M_U> inline AbstractMagma<U,M_U>::AbstractMagma( M_U m_U ) : m_m_U( move( m_U ) ) { static_assert( is_invocable_r_v<U,M_U,U,U> ); } template <typename U , typename M_U> inline U AbstractMagma<U,M_U>::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); } template <typename U> inline U VirtualMagma<U>::Sum( const U& u0 , const U& u1 ) { return Product( u0 , u1 ); } template <typename U> class VirtualMonoid : virtual public VirtualMagma<U> , virtual public VirtualPointedSet<U> {}; template <typename U = ll> class AdditiveMonoid : virtual public VirtualMonoid<U> , public PointedSet<U> { public: inline U Product( const U& u0 , const U& u1 ); }; template <typename U = ll> class MultiplicativeMonoid : virtual public VirtualMonoid<U> , public PointedSet<U> { public: inline MultiplicativeMonoid( const U& e_U ); inline U Product( const U& u0 , const U& u1 ); }; template <typename U , typename M_U> class AbstractMonoid : virtual public VirtualMonoid<U> , public AbstractMagma<U,M_U> , public PointedSet<U> { public: inline AbstractMonoid( M_U m_U , const U& e_U ); inline U Product( const U& u0 , const U& u1 ); }; template <typename U> inline MultiplicativeMonoid<U>::MultiplicativeMonoid( const U& e_U ) : PointedSet<U>( e_U ) {} template <typename U , typename M_U> inline AbstractMonoid<U,M_U>::AbstractMonoid( M_U m_U , const U& e_U ) : AbstractMagma<U,M_U>( move( m_U ) ) , PointedSet<U>( e_U ) {} template <typename U> inline U AdditiveMonoid<U>::Product( const U& u0 , const U& u1 ) { return u0 + u1; } template <typename U> inline U MultiplicativeMonoid<U>::Product( const U& u0 , const U& u1 ) { return u0 * u1; } template <typename U , typename M_U> inline U AbstractMonoid<U,M_U>::Product( const U& u0 , const U& u1 ) { return m_m_U( u0 , u1 ); } template <typename U> class VirtualGroup : virtual public VirtualMonoid<U> , virtual public VirtualPointedSet<U> , virtual public VirtualNSet<U> {}; template <typename U = ll> class AdditiveGroup : virtual public VirtualGroup<U> , public AdditiveMonoid<U> { public: inline U Transfer( const U& u ); }; template <typename U , typename M_U , typename I_U> class AbstractGroup : virtual public VirtualGroup<U> , public AbstractMonoid<U,M_U> , public AbstractNSet<U,I_U> { public: inline AbstractGroup( M_U m_U , const U& e_U , I_U i_U ); }; template <typename U , typename M_U , typename I_U> inline AbstractGroup<U,M_U,I_U>::AbstractGroup( M_U m_U , const U& e_U , I_U i_U ) : AbstractMonoid<U,M_U>( move( m_U ) , e_U ) , AbstractNSet<U,I_U>( move( i_U ) ) {} template <typename U> inline U AdditiveGroup<U>::Transfer( const U& u ) { return -u; } template <typename U , typename GROUP , typename MONOID> 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 <typename U = ll> class Ring : virtual public VirtualRing<U,AdditiveGroup<U>,MultiplicativeMonoid<U>> { public: inline Ring( const U& one_U ); }; template <typename U , typename A_U , typename I_U , typename M_U> class AbstractRing : virtual public VirtualRing<U,AbstractGroup<U,A_U,I_U>,AbstractMonoid<U,M_U>> { public: inline AbstractRing( A_U a_U , const U& z_U , I_U i_U , M_U m_U , const U& e_U ); }; template <typename U, typename GROUP , typename MONOID> inline VirtualRing<U,GROUP,MONOID>::VirtualRing( GROUP R0 , MONOID R1 ) : m_R0( move( R0 ) ) , m_R1( move( R1 ) ) {} template <typename U> inline Ring<U>::Ring( const U& one_U ) : VirtualRing<U,AdditiveGroup<U>,MultiplicativeMonoid<U>>( AdditiveGroup<U>() , MultiplicativeMonoid<U>( one_U ) ) {} template <typename U , typename A_U , typename I_U , typename M_U> inline AbstractRing<U,A_U,I_U,M_U>::AbstractRing( A_U a_U , const U& z_U , I_U i_U , M_U m_U , const U& e_U ) : VirtualRing<U,AbstractGroup<U,A_U,I_U>,AbstractMonoid<U,M_U>>( AbstractGroup<U,A_U,I_U>( move( a_U ) , z_U , move( i_U ) ) , AbstractMonoid<U,M_U>( move( m_U ) , e_U ) ) {} template <typename U, typename GROUP , typename MONOID> inline U VirtualRing<U,GROUP,MONOID>::Sum( const U& u0 , const U& u1 ) { return m_R0.Sum( u0 , u1 ); } template <typename U, typename GROUP , typename MONOID> inline const U& VirtualRing<U,GROUP,MONOID>::Zero() const noexcept { return m_R0.Zero(); } template <typename U, typename GROUP , typename MONOID> inline U VirtualRing<U,GROUP,MONOID>::Inverse( const U& u ) { return m_R0.Inverse( u ); } template <typename U, typename GROUP , typename MONOID> inline U VirtualRing<U,GROUP,MONOID>::Product( const U& u0 , const U& u1 ) { return m_R1.Product( u0 , u1 ); } template <typename U, typename GROUP , typename MONOID> inline const U& VirtualRing<U,GROUP,MONOID>::One() const noexcept { return m_R1.One(); } template <typename U, typename GROUP , typename MONOID> inline GROUP& VirtualRing<U,GROUP,MONOID>::AdditiveGroup() noexcept { return m_R0; } template <typename U, typename GROUP , typename MONOID> inline MONOID& VirtualRing<U,GROUP,MONOID>::MultiplicativeMonoid() noexcept { return m_R1; } #ifndef RET_TYPE #define RET_TYPE template <typename F , typename...Args> using ret_t = decltype( declval<F>()( declval<Args>()... ) ); #endif #ifndef INNER_TYPE #define INNER_TYPE template <typename T> using inner_t = typename T::type; #endif #ifndef decldecay_t #define decldecay_t( VAR ) decay_t<decltype( VAR )> #endif // Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nは互いに逆写像である仮想関数。 template <typename T , typename R1 , typename R2 , typename E> class VirtualGraph : public PointedSet<int> { 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<E,T> Edge( const T& t ); using type = T; }; template <typename E> class Graph : virtual public VirtualGraph<int,const int&,const int&,E> { public: inline Graph( const int& size , E edge ); inline const int& Enumeration( const int& i ); inline const int& Enumeration_inv( const int& t ); template <typename F> inline Graph<F> GetGraph( F edge ) const; }; template <typename T , typename Enum_T , typename Enum_T_inv , typename E> class EnumerationGraph : virtual public VirtualGraph<T,ret_t<Enum_T,int>,ret_t<Enum_T_inv,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<Enum_T,int> Enumeration( const int& i ); inline ret_t<Enum_T_inv,T> Enumeration_inv( const T& t ); template <typename F> inline EnumerationGraph<T,Enum_T,Enum_T_inv,F> GetGraph( F edge ) const; }; template <typename Enum_T , typename Enum_T_inv , typename E> EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) -> EnumerationGraph<decldecay_t(get<0>(declval<E>()(0).back())),Enum_T,Enum_T_inv,E>; // 推論補助のためにE::operator()はデフォルト引数が必要。 template <typename T , typename E> class MemorisationGraph : virtual public VirtualGraph<T,T,const int&,E> { private: int m_length; vector<T> m_memory; Map<T,int> 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 <typename F> inline MemorisationGraph<T,F> GetGraph( F edge ) const; }; template <typename E> MemorisationGraph( const int& size , E edge ) -> MemorisationGraph<decldecay_t(get<0>(declval<E>()().back())),E>; template <typename T , typename R1 , typename R2 , typename E> inline VirtualGraph<T,R1,R2,E>::VirtualGraph( const int& size , E edge ) : PointedSet<int>( size ) , m_edge( move( edge ) ) { static_assert( is_constructible_v<T,R1> && is_constructible_v<int,R2> && is_invocable_v<E,T> ); } template <typename E> inline Graph<E>::Graph( const int& size , E edge ) : VirtualGraph<int,const int&,const int&,E>( size , move( edge ) ) {} template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline EnumerationGraph<T,Enum_T,Enum_T_inv,E>::EnumerationGraph( const int& size , Enum_T enum_T , Enum_T_inv enum_T_inv , E edge ) : VirtualGraph<T,ret_t<Enum_T,int>,ret_t<Enum_T_inv,T>,E>( size , move( edge ) ) , m_enum_T( move( enum_T ) ) , m_enum_T_inv( move( enum_T_inv ) ) {} template <typename T , typename E> inline MemorisationGraph<T,E>::MemorisationGraph( const int& size , E edge ) : VirtualGraph<T,T,const int&,E>( size , move( edge ) ) , m_length() , m_memory() , m_memory_inv() {} template <typename T , typename R1 , typename R2 , typename E> inline ret_t<E,T> VirtualGraph<T,R1,R2,E>::Edge( const T& t ) { return m_edge( t ); } template <typename E> inline const int& Graph<E>::Enumeration( const int& i ) { return i; } template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline ret_t<Enum_T,int> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::Enumeration( const int& i ) { return m_enum_T( i ); } template <typename T , typename E> inline T MemorisationGraph<T,E>::Enumeration( const int& i ) { assert( 0 <= i && i < m_length ); return m_memory[i]; } template <typename E> inline const int& Graph<E>::Enumeration_inv( const int& i ) { return i; } template <typename T , typename Enum_T , typename Enum_T_inv , typename E> inline ret_t<Enum_T_inv,T> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::Enumeration_inv( const T& t ) { return m_enum_T_inv( t ); } template <typename T , typename E> inline const int& MemorisationGraph<T,E>::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 <typename T , typename R1 , typename R2 , typename E> void VirtualGraph<T,R1,R2,E>::Reset() {} template <typename T , typename E> inline void MemorisationGraph<T,E>::Reset() { m_length = 0; m_memory.clear(); m_memory_inv.clear(); } template <typename E> template <typename F> inline Graph<F> Graph<E>::GetGraph( F edge ) const { return Graph<F>( this->size() , move( edge ) ); } template <typename T , typename Enum_T , typename Enum_T_inv , typename E> template <typename F> inline EnumerationGraph<T,Enum_T,Enum_T_inv,F> EnumerationGraph<T,Enum_T,Enum_T_inv,E>::GetGraph( F edge ) const { return EnumerationGraph( this->size() , m_enum_T , m_enum_T_inv , move( edge ) ); } template <typename T , typename E> template <typename F> inline MemorisationGraph<T,F> MemorisationGraph<T,E>::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<bool> found( size ); \ vector<U> 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 <typename GRAPH , typename MONOID , typename U> class AbstractBellmanFord : public PointedSet<U> { private: GRAPH m_G; MONOID m_M; public: inline AbstractBellmanFord( GRAPH G , MONOID M , const U& infty ); // 負の閉路が存在すればfalse、存在しなければtrueを第1成分に返す。 tuple<bool,vector<U>> GetDistance( const inner_t<GRAPH>& t_start ); template <template <typename...> typename V> tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start , const V<inner_t<GRAPH>>& t_finals ); tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start ); }; template <typename GRAPH> class BellmanFord : public AbstractBellmanFord<GRAPH,AdditiveMonoid<>,ll> { public: inline BellmanFord( GRAPH G ); }; template <typename GRAPH , typename MONOID , typename U> inline AbstractBellmanFord<GRAPH,MONOID,U>::AbstractBellmanFord( GRAPH G , MONOID M , const U& infty ) : PointedSet<U>( infty ) , m_G( move( G ) ) , m_M( move( M ) ) { static_assert( ! is_same_v<U,int> ); } template <typename GRAPH> inline BellmanFord<GRAPH>::BellmanFord( GRAPH G ) : AbstractBellmanFord<GRAPH,AdditiveMonoid<>,ll>( move( G ) , AdditiveMonoid<>() , 4611686018427387904 ) {} template <typename GRAPH , typename MONOID , typename U> tuple<bool,vector<U>> AbstractBellmanFord<GRAPH,MONOID,U>::GetDistance( const inner_t<GRAPH>& t_start ) { BELLMAN_FORD_BODY( , ); m_G.Reset(); return { valid , move( weight ) }; } template <typename GRAPH , typename MONOID , typename U> template <template <typename...> typename V> tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> AbstractBellmanFord<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start , const V<inner_t<GRAPH>>& t_finals ) { BELLMAN_FORD_BODY( vector<int> prev( size ) , prev[j] = i ); vector<list<inner_t<GRAPH>>> path{}; if( valid ){ const int path_size = t_finals.size(); path.reserve( path_size ); for( auto itr = t_finals.begin() , end = t_finals.end() ; itr != end ; itr++ ){ list<inner_t<GRAPH>> path_j{}; const inner_t<GRAPH>& t_final = *itr; path_j.push_back( t_final ); int i = m_G.Enumeration_inv( t_final ); if( found[i] ){ while( i != i_start ){ i = prev[i]; path_j.push_front( m_G.Enumeration( i ) ); } } path.push_back( path_j ); } } m_G.Reset(); return { valid , move( weight ) , move( path ) }; } template <typename GRAPH , typename MONOID , typename U> tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> AbstractBellmanFord<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start ) { const int& size = m_G.size(); vector<inner_t<GRAPH>> t_finals( size ); for( int i = 0 ; i < size ; i++ ){ t_finals[i] = i; } return GetPath( t_start , t_finals ); } #define DIJKSTRA_BODY( INITIALISE_PREV , CHECK_FINAL , 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 ); \ set<pair<U,int>> vertex{}; \ vector<bool> found( size ); \ vector<U> weight( size , infty ); \ vertex.insert( pair<U,int>( weight[i_start] = zero , i_start ) ); \ INITIALISE_PREV; \ \ while( ! vertex.empty() ){ \ \ auto begin = vertex.begin(); \ auto [weight_i,i] = *begin; \ CHECK_FINAL; \ found[i] = true; \ vertex.erase( begin ); \ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); \ list<pair<U,int>> changed_vertex{}; \ \ for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \ \ auto&& j = m_G.Enumeration_inv( itr->first ); \ \ if( !found[j] ){ \ \ const U& edge_ij = itr->second; \ U temp = m_M.Sum( weight_i , edge_ij ); \ assert( !( temp < edge_ij ) && temp < infty ); \ U& weight_j = weight[j]; \ \ if( weight_j > temp ){ \ \ if( weight_j != infty ){ \ \ vertex.erase( pair<U,int>( weight_j , j ) ); \ \ } \ \ SET_PREV; \ changed_vertex.push_back( pair<U,int>( weight_j = move( temp ) , j ) ); \ \ } \ \ } \ \ } \ \ for( auto itr_changed = changed_vertex.begin() , end_changed = changed_vertex.end() ; itr_changed != end_changed ; itr_changed++ ){ \ \ vertex.insert( *itr_changed ); \ \ } \ \ } \ // GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。 // 入力の範囲内で要件 // (0) Mは全順序可換モノイド構造である。 // (1) E_Gの値の各成分の第2成分がM.Zero()以上である。 // (2) inftyがE_Gの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。 // (3) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。 // が成り立つ場合にのみサポート。 // 単一始点単一終点最短経路探索/経路復元なしO((|V_G|+|E_G|)log |V_G|) // 単一始点単一終点最短経路探索/経路復元ありO((|V_G|+|E_G|)log |V_G|) // 単一始点全終点最短経路探索/経路復元なしO((|V_G|+|E_G|)log |V_G|) // 単一始点全終点最短経路探索/経路復元ありO(|V_G|^2 + |E_G| log |V_G|) // O((|V_G|+|E_G|)log |V_G|)が間に合わない場合は、 // 始点からの距離を格納して一番近い未訪問点を全探策で探し距離を更新するO(|V_G|^2)版を検討。 template <typename GRAPH , typename MONOID , typename U> class AbstractDijkstra : public PointedSet<U> { private: GRAPH m_G; MONOID m_M; public: inline AbstractDijkstra( GRAPH G , MONOID M , const U& infty ); // 経路が存在しない場合の返り値はinfty U GetDistance( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final ); vector<U> GetDistance( const inner_t<GRAPH>& t_start ); pair<U,list<inner_t<GRAPH>>> GetPath( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final ); template <template <typename...> typename V> pair<vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start , const V<inner_t<GRAPH>>& t_finals ); pair<vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start ); }; template <typename GRAPH> class Dijkstra : public AbstractDijkstra<GRAPH,AdditiveMonoid<>,ll> { public: inline Dijkstra( GRAPH G ); }; template <typename GRAPH , typename MONOID , typename U> inline AbstractDijkstra<GRAPH,MONOID,U>::AbstractDijkstra( GRAPH G , MONOID M , const U& infty ) : PointedSet<U>( infty ) , m_G( move( G ) ) , m_M( move( M ) ) { static_assert( ! is_same_v<U,int> ); } template <typename GRAPH> inline Dijkstra<GRAPH>::Dijkstra( GRAPH G ) : AbstractDijkstra<GRAPH,AdditiveMonoid<>,ll>( G , AdditiveMonoid<>() , 4611686018427387904 ) {} template <typename GRAPH , typename MONOID , typename U> U AbstractDijkstra<GRAPH,MONOID,U>::GetDistance( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final ) { auto&& i_final = m_G.Enumeration_inv( t_final ); DIJKSTRA_BODY( , if( i == i_final ){ break; } , ); U answer{ move( weight[i_final] ) }; m_G.Reset(); return answer; } template <typename GRAPH , typename MONOID , typename U> vector<U> AbstractDijkstra<GRAPH,MONOID,U>::GetDistance( const inner_t<GRAPH>& t_start ) { DIJKSTRA_BODY( , , ); m_G.Reset(); return weight; } template <typename GRAPH , typename MONOID , typename U> pair<U,list<inner_t<GRAPH>>> AbstractDijkstra<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final ) { auto&& i_final = m_G.Enumeration_inv( t_final ); DIJKSTRA_BODY( vector<int> prev( size ) , if( i == i_final ){ break; } , prev[j] = i ); int i = i_final; list<inner_t<GRAPH>> path{}; path.push_back( t_final ); if( found[i] ){ while( i != i_start ){ i = prev[i]; path.push_front( m_G.Enumeration( i ) ); } } U answer{ move( weight[i_final] ) }; m_G.Reset(); return { move( answer ) , move( path ) }; } template <typename GRAPH , typename MONOID , typename U> template <template <typename...> typename V> pair<vector<U>,vector<list<inner_t<GRAPH>>>> AbstractDijkstra<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start , const V<inner_t<GRAPH>>& t_finals ) { DIJKSTRA_BODY( vector<int> prev( size ) , , prev[j] = i ); const int path_size = t_finals.size(); vector<list<inner_t<GRAPH>>> path; path.reserve( path_size ); for( auto itr = t_finals.begin() , end = t_finals.end() ; itr != end ; itr++ ){ list<inner_t<GRAPH>> path_j{}; const inner_t<GRAPH>& t_final = *itr; path_j.push_back( t_final ); int i = m_G.Enumeration_inv( t_final ); if( found[i] ){ while( i != i_start ){ i = prev[i]; path_j.push_front( m_G.Enumeration( i ) ); } } path.push_back( path_j ); } m_G.Reset(); return { move( weight ) , move( path ) }; } template <typename GRAPH , typename MONOID , typename U> pair<vector<U>,vector<list<inner_t<GRAPH>>>> AbstractDijkstra<GRAPH,MONOID,U>::GetPath( const inner_t<GRAPH>& t_start ) { const int& size = m_G.size(); vector<inner_t<GRAPH>> t_finals( size ); for( int i = 0 ; i < size ; i++ ){ t_finals[i] = i; } return GetPath( t_start , t_finals ); } #define POTENTIALISED_DIJKSTRA_BODY( GET , WEIGHT , ... ) \ const U& infty = this->Infty(); \ if( m_valid ){ \ \ const U& zero = m_M.Zero(); \ auto edge = [&]( const T& t ){ \ \ const U& potential_i = m_potential[m_G.Enumeration_inv( t )]; \ assert( potential_i < infty ); \ auto edge_i = m_G.Edge( t ); \ list<pair<T,U>> answer{}; \ \ for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \ \ auto& e = *itr; \ \ if( m_on( e ) ){ \ \ const auto& v_j = get<0>( e ); \ U& w_j = get<1>( e ); \ const U& potential_j = m_potential[m_G.Enumeration_inv( v_j )]; \ assert( w_j < infty && potential_j < infty ); \ const U potential_j_inv = m_M.Inverse( potential_j ); \ w_j = m_M.Sum( m_M.Sum( w_j , potential_i ) , potential_j_inv ); \ assert( !( w_j < zero ) && w_j < infty ); \ answer.push_back( { v_j , move( w_j ) } ); \ \ } \ \ } \ \ return answer; \ \ }; \ \ auto G = m_G.GetGraph( move( edge ) ); \ AbstractDijkstra d{ move( G ) , m_M , infty }; \ auto value = d.GET; \ const int& size = m_G.size(); \ \ for( int i = 0 ; i < size ; i++ ){ \ \ auto& weight_i = WEIGHT[i]; \ \ if( weight_i != infty ){ \ \ weight_i = m_M.Sum( weight_i , m_potential[i] ); \ \ } \ \ } \ \ return { m_valid , __VA_ARGS__ }; \ \ } \ \ auto edge = [&]( const T& t ){ \ \ auto&& edge_i = m_G.Edge( t ); \ list<pair<T,U>> answer{}; \ \ for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ \ \ if( m_on( *itr ) ){ \ \ answer.push_back( { get<0>( *itr ) , get<1>( *itr ) } ); \ \ } \ \ } \ \ return answer; \ \ }; \ \ auto G = m_G.GetGraph( move( edge ) ); \ AbstractBellmanFord d{ G , m_M , infty }; \ return d.GET; \ // GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。 // Onは写像on:im(edge)->\{0,1\}に相当する型。 // 入力の範囲内で要件 // (0) Mは全順序アーベル群構造である。 // (1) inftyが「E_Gの値の各成分の第2成分と2点間ポテンシャル差の和」の|V_G|個以下の和で表せるいかなる数よりも大きい。 // (2) Vの各要素u,vに対し、辺u->vが複数存在する場合は重みが最小のものが前にpushされている。 // が成り立つ場合にのみサポート。 // 負辺を含む場合/含まない場合 // 構築O(|V_G| |E_G|)/O(|V_G|) // 単一始点全終点最短経路探索/経路復元なしO((|V_G|+|E_G|)log |V_G|) // 単一始点全終点最短経路探索/経路復元ありO(|V_G|^2 + |E_G| log |V_G|) template <typename T , typename GRAPH , typename GROUP , typename U , typename On> class AbstractPotentialisedDijkstra : public PointedSet<U> { private: GRAPH m_G; GROUP m_M; T m_t_start; // 全ての辺を許容する場合に始点から負のループに到達可能か否か。 bool m_valid; // 全ての辺を許容する場合の始点からのコスト。 vector<U> m_potential; // どの辺を許容するかを決める関数オブジェクト。 On m_on; public: inline AbstractPotentialisedDijkstra( GRAPH G , GROUP M , const T& t_start , const U& infty , On on , const bool& negative = true ); inline AbstractPotentialisedDijkstra( GRAPH G , GROUP M , const T& t_start , const U& infty , const bool& valid , vector<U> potential , On on ); inline const bool& Valid() const noexcept; inline const vector<U>& Potential() const noexcept; inline void SetPotential( const bool& valid , vector<U> potential ); tuple<bool,vector<U>> GetDistance(); template <typename...Args> tuple<bool,vector<U>,vector<list<T>>> GetPath( const Args&... args ); }; template <typename T , typename GRAPH , typename On> class PotentialisedDijkstra : public AbstractPotentialisedDijkstra<T,GRAPH,AdditiveGroup<>,ll,On> { public: template <typename...Args> inline PotentialisedDijkstra( GRAPH G , const T& t_start , Args&&... args ); }; template <typename T , typename GRAPH , typename GROUP , typename U , typename On> inline AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::AbstractPotentialisedDijkstra( GRAPH G , GROUP M , const T& t_start , const U& infty , On on , const bool& negative ) : AbstractPotentialisedDijkstra( move( G ) , move( M ) , t_start , infty , true , vector<U>() , move( on ) ) { if( negative ){ auto edge = [&]( const int& t ){ auto&& edge_i = m_G.Edge( t ); list<pair<T,U>> answer{}; for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ const auto& e = *itr; answer.push_back( { get<0>( e ) , get<1>( e ) } ); } return answer; }; auto G = m_G.GetGraph( move( edge ) ); AbstractBellmanFord bf{ move( G ) , m_M , infty }; auto [valid,potential] = bf.GetDistance( m_t_start ); m_valid = valid; m_potential = move( potential ); } else { m_potential = vector<U>( m_G.size() , m_M.Zero() ); } } template <typename T , typename GRAPH , typename GROUP , typename U , typename On> inline AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::AbstractPotentialisedDijkstra( GRAPH G , GROUP M , const T& t_start , const U& infty , const bool& valid , vector<U> potential , On on ) : PointedSet<U>( infty ) , m_G( move( G ) ) , m_M( move( M ) ) , m_t_start( t_start ) , m_valid( valid ) , m_potential( potential ) , m_on( move( on ) ) { static_assert( is_invocable_r_v<bool,On,decltype(declval<GRAPH>().Edge(declval<T>()).back())> ); } template <typename T , typename GRAPH , typename On> template <typename...Args> inline PotentialisedDijkstra<T,GRAPH,On>::PotentialisedDijkstra( GRAPH G , const T& t_start , Args&&... args ) : AbstractPotentialisedDijkstra<T,GRAPH,AdditiveGroup<>,ll,On>( move( G ) , AdditiveGroup<>() , t_start , 4611686018427387904 , forward<decay_t<Args>>( args )... ) {} template <typename T , typename GRAPH , typename GROUP , typename U , typename On> inline const bool& AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::Valid() const noexcept { return m_valid; } template <typename T , typename GRAPH , typename GROUP , typename U , typename On> inline const vector<U>& AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::Potential() const noexcept { return m_potential; } template <typename T , typename GRAPH , typename GROUP , typename U , typename On> inline void AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::SetPotential( const bool& valid , vector<U> potential ) { assert( int( potential.size() ) == m_G.size() ); m_valid = valid; m_potential = move( potential ); } template <typename T , typename GRAPH , typename GROUP , typename U , typename On> tuple<bool,vector<U>> AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::GetDistance() { POTENTIALISED_DIJKSTRA_BODY( GetDistance( m_t_start ) , value , move( value ) ); } template <typename T , typename GRAPH , typename GROUP , typename U , typename On> template <typename...Args> tuple<bool,vector<U>,vector<list<T>>> AbstractPotentialisedDijkstra<T,GRAPH,GROUP,U,On>::GetPath( const Args&... args ) { POTENTIALISED_DIJKSTRA_BODY( GetPath( m_t_start , args... ) , get<0>( value ) , move( get<0>( value ) ) , move( get<1>( value ) ) ); } // GRAPHはグラフG=(V_G,E_G:T->(T \times U(コスト) \times U(容量))^{< \omega})に相当する型。 // 入力の範囲内で要件 // (0) Rは全順序環構造である。 // (1) E_Gの値の各成分の第2成分がM.Zero()以上である。 // (2) inftyが「E_Gの値の各成分の第2成分と2点間ポテンシャル差の和」の|V_G|個以下の和のf倍で表せるいかなる数よりも大きい。 // (3) Vの各要素u,vに対し、辺u->vが複数存在しない。 // が成り立つ場合にのみサポート。 // 単一始点単一終点最小費用流路探索O(F (|V_G|+|E_G|)log |V_G|) template <typename GRAPH , typename RING , typename U> class AbstractMinimalCostFlow : public PointedSet<U> { private: GRAPH m_G; RING m_R; public: inline AbstractMinimalCostFlow( GRAPH G , RING R , const U& infty ); pair<U,vector<vector<tuple<inner_t<GRAPH>,U>>>> GetFlow( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , U f ); }; template <typename GRAPH , typename U> class MinimalCostFlow : public AbstractMinimalCostFlow<GRAPH,Ring<U>,U> { public: inline MinimalCostFlow( GRAPH G , const U& one_U , const U& infty ); }; template <typename GRAPH , typename RING , typename U> inline AbstractMinimalCostFlow<GRAPH,RING,U>::AbstractMinimalCostFlow( GRAPH G , RING R , const U& infty ) : PointedSet<U>( infty ) , m_G( move( G ) ) , m_R( move( R ) ) {} template <typename GRAPH , typename U> inline MinimalCostFlow<GRAPH,U>::MinimalCostFlow( GRAPH G , const U& one_U , const U& infty ) : AbstractMinimalCostFlow<GRAPH,Ring<U>,U>( move( G ) , Ring<U>( one_U ) , infty ) {} template <typename GRAPH , typename RING , typename U> pair<U,vector<vector<tuple<inner_t<GRAPH>,U>>>> AbstractMinimalCostFlow<GRAPH,RING,U>::GetFlow( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , U f ) { using T = inner_t<GRAPH>; const U& zero = m_R.Zero(); const U& infty = this->Infty(); const int& size = m_G.size(); vector<vector<tuple<int,U,U,bool,int>>> rest( size ); vector<vector<tuple<T,U>>> flow( size ); int edge_num = 0; for( int i = 0 ; i < size ; i++ ){ auto&& ui = m_G.Enumeration( i ); auto&& edge_i = m_G.Edge( ui ); for( auto itr = edge_i.begin() , end = edge_i.end() ; itr != end ; itr++ ){ const auto& [vj,wj,fj] = *itr; assert( ui != vj && !( wj < zero ) && wj < infty && !( fj < zero ) && fj < infty ); auto&& j = m_G.Enumeration_inv( vj ); rest[i].push_back( { j , wj , fj , false , edge_num } ); rest[j].push_back( { i , m_R.Inverse( wj ) , zero , true , edge_num } ); flow[i].push_back( { vj , 0 } ); edge_num++; } } for( int i = 0 ; i < size ; i++ ){ auto& rest_i = rest[i]; sort( rest_i.begin() , rest_i.end() ); } vector<tuple<int,int,int,int>> edge_pair( edge_num , { -1 , -1 , -1 , -1 } ); for( int i = 0 ; i < size ; i++ ){ const auto& rest_i = rest[i]; const int size_i = rest_i.size(); for( int j = 0 ; j < size_i ; j++ ){ const auto& rest_ij = rest_i[j]; auto& [i_0,j_0,i_1,j_1] = edge_pair[get<4>( rest_ij )]; if( i_0 == -1 ){ i_0 = i; j_0 = j; } else { i_1 = i; j_1 = j; } } } auto edge = [&]( const T& t ) -> const vector<tuple<int,U,U,bool,int>>& { return rest[m_G.Enumeration_inv( t )]; }; auto on = [&]( const tuple<T,U,U,bool,int>& e ) { return zero < get<2>( e ); }; auto G = m_G.GetGraph( move( edge ) ); AbstractPotentialisedDijkstra pd{ move( G ) , m_R.AdditiveGroup() , t_start , infty , move( on ) , false }; auto&& i_start = m_G.Enumeration_inv( t_start ); list<T> t_finals = { t_final }; U w = zero; while( zero < f ){ auto [valid,weight,paths] = pd.GetPath( t_finals ); assert( valid ); pd.SetPotential( valid , move( weight ) ); auto& path = paths.front(); auto itr_path = path.begin() , itr_path_prev = itr_path , end_path = path.end(); assert( itr_path != end_path ); int i = i_start; list<tuple<int,int,int,int>> flow_num{}; U f_min = f; while( ++itr_path != end_path ){ T t = *itr_path; flow_num.push_back( { i , m_G.Enumeration_inv( t ) , -1 , -1 } ); auto& [i_curr,i_next,j_1,j_2] = flow_num.back(); const auto& rest_i = rest[i_curr]; int size_i = rest_i.size(); for( int j = 0 ; j < size_i ; j++ ){ const auto& [vj,wj,fj,rj,numj] = rest_i[j]; if( zero < fj && vj == t ){ j_1 = j; fj < f_min ? f_min = fj : f_min; if( rj ){ i_curr = i_next; t = *itr_path_prev; } break; } } assert( j_1 != -1 ); auto& flow_i = flow[i_curr]; size_i = flow_i.size(); for( int j = 0 ; j < size_i ; j++ ){ const auto& [vj,fj] = flow_i[j]; if( vj == t ){ j_2 = j; break; } } assert( j_2 != -1 ); i_curr = i; i = i_next; itr_path_prev = itr_path; } const U f_min_minus = m_R.Inverse( f_min ); U w_diff = zero; for( auto itr = flow_num.begin() , end = flow_num.end() ; itr != end ; itr++ ){ const auto& [i_curr,i_next,j_1,j_2] = *itr; auto& [vj,wj,fj,rj,numj] = rest[i_curr][j_1]; const auto& edge_pair_i = edge_pair[numj]; const int& j_3 = get<0>( edge_pair_i ) == i_curr ? get<3>( edge_pair_i ) : get<1>( edge_pair_i ); auto& fj_inv = get<2>( rest[i_next][j_3] ); auto& f_curr = get<1>( flow[rj ? i_next : i_curr][j_2] ); w_diff = m_R.Sum( w_diff , wj ); fj = m_R.Sum( fj , f_min_minus ); fj_inv = m_R.Sum( fj_inv , f_min ); f_curr = m_R.Sum( f_curr , f_min ); } f = m_R.Sum( f , f_min_minus ); w = m_R.Sum( w , m_R.Product( f_min , w_diff ) ); } return { move( w ) , move( flow ) }; } // AAA 常設でないライブラリは以上に挿入する。 #define INCLUDE_SUB #include __FILE__ #else // INCLUDE_LIBRARY #ifdef DEBUG #define _GLIBCXX_DEBUG #define REPEAT_MAIN( BOUND ) START_MAIN; signal( SIGABRT , &AlertAbort ); AutoCheck( exec_mode , use_getline ); if( exec_mode == sample_debug_mode || exec_mode == submission_debug_mode || exec_mode == library_search_mode ){ return 0; } else if( exec_mode == experiment_mode ){ Experiment(); return 0; } else if( exec_mode == small_test_mode ){ SmallTest(); return 0; }; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if( exec_mode == solve_mode ){ if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } } else if( exec_mode == random_test_mode ){ CERR( "ランダムテストを行う回数を指定してください。" ); SET_LL( test_case_num ); } FINISH_MAIN #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , DEBUG_VALUE ) #define ASSERT( A , MIN , MAX ) CERR( "ASSERTチェック: " , ( MIN ) , ( ( MIN ) <= A ? "<=" : ">" ) , A , ( A <= ( MAX ) ? "<=" : ">" ) , ( MAX ) ); assert( ( MIN ) <= A && A <= ( MAX ) ) #define SET_ASSERT( A , MIN , MAX ) if( exec_mode == solve_mode ){ SET_LL( A ); ASSERT( A , MIN , MAX ); } else if( exec_mode == random_test_mode ){ CERR( #A , " = " , ( A = GetRand( MIN , MAX ) ) ); } else { assert( false ); } #define SOLVE_ONLY static_assert( __FUNCTION__[0] == 'S' ) #define CERR( ... ) VariadicCout( cerr , __VA_ARGS__ ) << endl #define COUT( ... ) VariadicCout( cout << "出力: " , __VA_ARGS__ ) << endl #define CERR_A( A , N ) OUTPUT_ARRAY( cerr , A , N ) << endl #define COUT_A( A , N ) cout << "出力: "; OUTPUT_ARRAY( cout , A , N ) << endl #define CERR_ITR( A ) OUTPUT_ITR( cerr , A ) << endl #define COUT_ITR( A ) cout << "出力: "; OUTPUT_ITR( cout , A ) << endl #else #pragma GCC optimize ( "O3" ) #pragma GCC optimize ( "unroll-loops" ) #pragma GCC target ( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) #define REPEAT_MAIN( BOUND ) START_MAIN; CEXPR( int , bound_test_case_num , BOUND ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } FINISH_MAIN #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE ) #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) ) #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX ) #define SOLVE_ONLY #define CERR( ... ) #define COUT( ... ) VariadicCout( cout , __VA_ARGS__ ) << ENDL #define CERR_A( A , N ) #define COUT_A( A , N ) OUTPUT_ARRAY( cout , A , N ) << ENDL #define CERR_ITR( A ) #define COUT_ITR( A ) OUTPUT_ITR( cout , A ) << ENDL #endif #ifdef REACTIVE #define ENDL endl #else #define ENDL "\n" #endif #ifdef USE_GETLINE #define SET_LL( A ) { GETLINE( A ## _str ); A = stoll( A ## _str ); } #define GETLINE_SEPARATE( SEPARATOR , ... ) SOLVE_ONLY; string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ ) #define GETLINE( ... ) SOLVE_ONLY; GETLINE_SEPARATE( '\n' , __VA_ARGS__ ) #else #define SET_LL( A ) cin >> A #define CIN( LL , ... ) SOLVE_ONLY; LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ ) #define SET_A( A , N ) SOLVE_ONLY; FOR( VARIABLE_FOR_CIN_A , 0 , N ){ cin >> A[VARIABLE_FOR_CIN_A]; } #define CIN_A( LL , A , N ) vector<LL> A( N ); SET_A( A , N ); #endif #include <bits/stdc++.h> using namespace std; using uint = unsigned int; using ll = long long; using ull = unsigned long long; using ld = long double; using lld = __float128; template <typename INT> using T2 = pair<INT,INT>; template <typename INT> using T3 = tuple<INT,INT,INT>; template <typename INT> using T4 = tuple<INT,INT,INT,INT>; using path = pair<int,ll>; #define ATT __attribute__( ( target( "sse4.2,fma,avx2,popcnt,lzcnt,bmi2" ) ) ) #define START_MAIN int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr ) #define FINISH_MAIN REPEAT( test_case_num ){ if constexpr( bound_test_case_num > 1 ){ CERR( "testcase " , VARIABLE_FOR_REPEAT_test_case_num , ":" ); } Solve(); CERR( "" ); } } #define START_WATCH chrono::system_clock::time_point watch = chrono::system_clock::now() #define CURRENT_TIME static_cast<double>( chrono::duration_cast<chrono::microseconds>( chrono::system_clock::now() - watch ).count() / 1000.0 ) #define CHECK_WATCH( TL_MS ) ( CURRENT_TIME < TL_MS - 100.0 ) #define decldecay_t( VAR ) decay_t<decltype( VAR )> #define CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE #define CIN_ASSERT( A , MIN , MAX ) decldecay_t( MAX ) A; SET_ASSERT( A , MIN , MAX ) #define FOR( VAR , INITIAL , FINAL_PLUS_ONE ) for( decldecay_t( FINAL_PLUS_ONE ) VAR = INITIAL ; VAR < FINAL_PLUS_ONE ; VAR ++ ) #define FOREQ( VAR , INITIAL , FINAL ) for( decldecay_t( FINAL ) VAR = INITIAL ; VAR <= FINAL ; VAR ++ ) #define FOREQINV( VAR , INITIAL , FINAL ) for( decldecay_t( INITIAL ) VAR = INITIAL ; VAR + 1 > FINAL ; VAR -- ) #define AUTO_ITR( ARRAY ) auto itr_ ## ARRAY = ARRAY .begin() , end_ ## ARRAY = ARRAY .end() #define FOR_ITR( ARRAY ) for( AUTO_ITR( ARRAY ) , itr = itr_ ## ARRAY ; itr_ ## ARRAY != end_ ## ARRAY ; itr_ ## ARRAY ++ , itr++ ) #define REPEAT( HOW_MANY_TIMES ) FOR( VARIABLE_FOR_REPEAT_ ## HOW_MANY_TIMES , 0 , HOW_MANY_TIMES ) #define SET_PRECISION( DECIMAL_DIGITS ) cout << fixed << setprecision( DECIMAL_DIGITS ) #define OUTPUT_ARRAY( OS , A , N ) FOR( VARIABLE_FOR_OUTPUT_ARRAY , 0 , N ){ OS << A[VARIABLE_FOR_OUTPUT_ARRAY] << (VARIABLE_FOR_OUTPUT_ARRAY==N-1?"":" "); } OS #define OUTPUT_ITR( OS , A ) { auto ITERATOR_FOR_OUTPUT_ITR = A.begin() , END_FOR_OUTPUT_ITR = A.end(); bool VARIABLE_FOR_OUTPUT_ITR = ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR; while( VARIABLE_FOR_OUTPUT_ITR ){ OS << *ITERATOR_FOR_COUT_ITR; ( VARIABLE_FOR_OUTPUT_ITR = ++ITERATOR_FOR_COUT_ITR != END_FOR_COUT_ITR ) ? OS : OS << " "; } } OS #define RETURN( ... ) SOLVE_ONLY; COUT( __VA_ARGS__ ); return #define COMPARE( ... ) auto naive = Naive( __VA_ARGS__ ); auto answer = Answer( __VA_ARGS__ ); bool match = naive == answer; COUT( "(" , #__VA_ARGS__ , ") == (" , __VA_ARGS__ , ") : Naive == " , naive , match ? "==" : "!=" , answer , "== Answer" ); if( !match ){ return; } // 入出力用 template <class Traits> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is ) { return is; } template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicCin( basic_istream<char,Traits>& is , Arg& arg , ARGS&... args ) { return VariadicCin( is >> arg , args... ); } template <class Traits> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator ) { return is; } template <class Traits , typename Arg , typename... ARGS> inline basic_istream<char,Traits>& VariadicGetline( basic_istream<char,Traits>& is , const char& separator , Arg& arg , ARGS&... args ) { return VariadicGetline( getline( is , arg , separator ) , separator , args... ); } template <class Traits , typename Arg> inline basic_ostream<char,Traits>& operator<<( basic_ostream<char,Traits>& os , const vector<Arg>& arg ) { auto begin = arg.begin() , end = arg.end(); auto itr = begin; while( itr != end ){ ( itr == begin ? os : os << " " ) << *itr; itr++; } return os; } template <class Traits , typename Arg> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg& arg ) { return os << arg; } template <class Traits , typename Arg1 , typename Arg2 , typename... ARGS> inline basic_ostream<char,Traits>& VariadicCout( basic_ostream<char,Traits>& os , const Arg1& arg1 , const Arg2& arg2 , const ARGS&... args ) { return VariadicCout( os << arg1 << " " , arg2 , args... ); } // デバッグ用 #ifdef DEBUG inline void AlertAbort( int n ) { CERR( "abort関数が呼ばれました。assertマクロのメッセージが出力されていない場合はオーバーフローの有無を確認をしてください。" ); } void AutoCheck( int& exec_mode , const bool& use_getline ); inline void Solve(); inline void Experiment(); inline void SmallTest(); inline void RandomTest(); ll GetRand( const ll& Rand_min , const ll& Rand_max ); int exec_mode; CEXPR( int , solve_mode , 0 ); CEXPR( int , sample_debug_mode , 1 ); CEXPR( int , submission_debug_mode , 2 ); CEXPR( int , library_search_mode , 3 ); CEXPR( int , experiment_mode , 4 ); CEXPR( int , small_test_mode , 5 ); CEXPR( int , random_test_mode , 6 ); #ifdef USE_GETLINE CEXPR( bool , use_getline , true ); #else CEXPR( bool , use_getline , false ); #endif #else ll GetRand( const ll& Rand_min , const ll& Rand_max ) { ll answer = time( NULL ); return answer * rand() % ( Rand_max + 1 - Rand_min ) + Rand_min; } #endif // 圧縮用 #define TE template #define TY typename #define US using #define ST static #define IN inline #define CL class #define PU public #define OP operator #define CE constexpr #define CO const #define NE noexcept #define RE return #define WH while #define VO void #define VE vector #define LI list #define BE begin #define EN end #define SZ size #define MO move #define TH this #define CRI CO int& #define CRUI CO uint& #define CRL CO ll& // VVV 常設ライブラリは以下に挿入する。 // Map // c:/Users/user/Documents/Programming/Mathematics/Function/Map CL is_ordered{PU:is_ordered()= delete;TE <TY T> ST CE auto Check(CO T& t)-> decltype(t < t,true_type());ST CE false_type Check(...);TE <TY T> ST CE CO bool value = is_same_v< decltype(Check(declval<T>())),true_type >;}; TE <TY T , TY U>US Map = conditional_t<is_constructible_v<unordered_map<T,int>>,unordered_map<T,U>,conditional_t<is_ordered::value<T>,map<T,U>,void>>; // AAA 常設ライブラリは以上に挿入する。 #define INCLUDE_LIBRARY #include __FILE__ #endif // INCLUDE_LIBRARY #endif // INCLUDE_SUB #endif // INCLUDE_MAIN