結果
問題 | No.2915 辺更新価値最大化 |
ユーザー | 👑 p-adic |
提出日時 | 2024-02-09 18:27:09 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
AC
|
実行時間 | 161 ms / 2,000 ms |
コード長 | 51,793 bytes |
コンパイル時間 | 5,000 ms |
コンパイル使用メモリ | 273,904 KB |
実行使用メモリ | 6,944 KB |
最終ジャッジ日時 | 2024-07-29 20:30:39 |
合計ジャッジ時間 | 8,374 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
6,816 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,944 KB |
testcase_04 | AC | 2 ms
6,940 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 2 ms
6,940 KB |
testcase_07 | AC | 124 ms
6,940 KB |
testcase_08 | AC | 68 ms
6,940 KB |
testcase_09 | AC | 66 ms
6,940 KB |
testcase_10 | AC | 62 ms
6,940 KB |
testcase_11 | AC | 68 ms
6,944 KB |
testcase_12 | AC | 68 ms
6,940 KB |
testcase_13 | AC | 138 ms
6,940 KB |
testcase_14 | AC | 136 ms
6,940 KB |
testcase_15 | AC | 155 ms
6,944 KB |
testcase_16 | AC | 161 ms
6,940 KB |
testcase_17 | AC | 147 ms
6,944 KB |
testcase_18 | AC | 145 ms
6,940 KB |
testcase_19 | AC | 147 ms
6,944 KB |
testcase_20 | AC | 147 ms
6,944 KB |
testcase_21 | AC | 89 ms
6,940 KB |
testcase_22 | AC | 38 ms
6,940 KB |
testcase_23 | AC | 138 ms
6,940 KB |
testcase_24 | AC | 139 ms
6,940 KB |
testcase_25 | AC | 128 ms
6,940 KB |
testcase_26 | AC | 115 ms
6,940 KB |
testcase_27 | AC | 153 ms
6,944 KB |
ソースコード
#ifndef INCLUDE_MODE #define INCLUDE_MODE // #define REACTIVE // #define USE_GETLINE #endif #ifdef INCLUDE_MAIN inline void Solve() { CEXPR( int , bound , 1e3 ); CIN_ASSERT( N , 2 , bound ); CIN_ASSERT( M , 1 , bound ); CIN_ASSERT( Q , 1 , bound ); using path_type = tuple<int,ll,int>; vector<vector<path_type>> e( N ); FOR( j , 0 , M ){ CIN_ASSERT( uj , 1 , N ); CIN_ASSERT( vj , 1 , N ); assert( uj != vj ); uj--; vj--; CIN_ASSERT( wj , -bound , bound ); e[uj].push_back( { vj , -wj , j } ); } auto edge = [&]( const int& i ){ return e[i]; }; Graph graph{ N , edge }; vector<bool> fixed( M , true ); auto on = [&]( const path_type& e ){ return fixed[get<2>( e )]; }; PotentialisedDijkstra pdijk{ graph , 0 , on , true }; assert( pdijk.Valid() ); CEXPR( bool , many_edges , false ); FOR( q , 0 , Q ){ CIN_ASSERT( j , 1 , M ); j--; fixed[j] = !fixed[j]; ll answer = get<1>( pdijk.GetDistance( many_edges ) )[N-1]; if( answer == pdijk.Infty() ){ COUT( "NaN" ); } else { COUT( -answer ); } } } REPEAT_MAIN(1); #else // INCLUDE_MAIN #ifdef INCLUDE_LIBRARY // https://github.com/p-adic/cpp // VVV ライブラリは以下に挿入する。 class is_ordered { private: is_ordered() = delete; template <typename T> static constexpr auto Check( const T& t ) -> decltype( t < t , true_type() ); static constexpr false_type Check( ... ); public: template <typename T> static constexpr const bool value = is_same_v< decltype( Check( declval<T>() ) ) , true_type >; }; template <typename INT , template <typename...> typename T> struct hash<T<INT>> : public hash<INT> { inline size_t operator()( const T<INT>& n ) const; }; template <typename T , typename U> using Map = conditional_t<is_constructible_v<unordered_map<T,int>>,unordered_map<T,U>,conditional_t<is_ordered::value<T>,map<T,U>,void>>; // Map<T,U>は // - unordered_map<T,U>()がwell-formedならばunordered_map<T,U> // - そうでなくoperator<(declval<T>(),declval<T>())がwell-formedならばmap<T,U> // - そうでないならばvoid template <typename INT , template <typename...> typename T> inline size_t hash<T<INT>>::operator()( const T<INT>& n ) const { return hash<INT>::operator()( n.Represent() ); } #define DECLARATION_OF_CPOINT( POINT ) inline const U& POINT() const noexcept #define DECLARATION_OF_POINT( POINT ) inline U& POINT() noexcept #define DEFINITION_OF_CPOINT( POINT ) template <typename U> inline const U& VirtualPointedSet<U>::POINT() const noexcept { return Point(); } #define DEFINITION_OF_POINT( POINT ) template <typename U> inline U& VirtualPointedSet<U>::POINT() noexcept { return Point(); } // - インタフェースをなるべく抽象型で与えて仮想継承する。 // - 具体的構造が2種類以上あるものはもちろん抽象型を仮想継承する。 // - VirtualPointedSetのように具体的構造が1種類しかないものも仮想継承のコンストラクタ呼び出しを // 省略するためになるべく抽象型を用意する。 // - AbstractDijkstraのように全ての具体的構造が1つの具体的構造の派生である場合は // インタフェースを必要としない。 // - コンストラクタはなるべく省略できるようにするが、ポインタはメンバ変数にしない。 // - VirtualGraphのように具体的構造が2種類以上あるもので全てに共通の定義本体を持つ関数(Edge)が // 必要な場合は実装が膨れ上がらないように抽象型に関数の定義をし、そのため抽象型にメンバ変数が // 必要になる場合はコンストラクタを非自明なものにする // - 代わりにポインタを抽象型のメンバとして // 派生クラスのコンストラクタの定義内でアドレスを渡すようにすると、ムーブなどで意図せず // ポインタの指すアドレスが意図通りでなくなることに注意する。 template <typename U> class UnderlyingSet { public: using type = U; }; template <typename U> class VirtualPointedSet : virtual public UnderlyingSet<U> { public: virtual const U& Point() const noexcept = 0; virtual U& Point() noexcept = 0; DECLARATION_OF_CPOINT( Unit ); DECLARATION_OF_CPOINT( Zero ); DECLARATION_OF_CPOINT( One ); DECLARATION_OF_CPOINT( Infty ); DECLARATION_OF_POINT( init ); DECLARATION_OF_POINT( root ); }; 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; inline U& Point() noexcept; }; template <typename U> class VirtualNSet : virtual public UnderlyingSet<U> { 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 : virtual public UnderlyingSet<U> { public: virtual U Product( const U& u0 , const U& u1 ) = 0; inline U Sum( const U& u0 , const U& u1 ); }; template <typename U = ll> class AdditiveMagma : virtual public VirtualMagma<U> { public: inline U Product( const U& u0 , const U& u1 ); }; template <typename U = ll> class MultiplicativeMagma : virtual public VirtualMagma<U> { public: inline U Product( 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 U& PointedSet<U>::Point() noexcept { return m_b_U; } DEFINITION_OF_CPOINT( Unit ); DEFINITION_OF_CPOINT( Zero ); DEFINITION_OF_CPOINT( One ); DEFINITION_OF_CPOINT( Infty ); DEFINITION_OF_POINT( init ); DEFINITION_OF_POINT( root ); template <typename U , typename F_U> inline AbstractNSet<U,F_U>::AbstractNSet( F_U& f_U ) : m_f_U( 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( m_U ) { static_assert( is_invocable_r_v<U,M_U,U,U> ); } template <typename U> inline U AdditiveMagma<U>::Product( const U& u0 , const U& u1 ) { return u0 + u1; } template <typename U> inline U MultiplicativeMagma<U>::Product( const U& u0 , const U& u1 ) { return u0 * u1; } 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 AdditiveMagma<U> , public PointedSet<U> {}; template <typename U = ll> class MultiplicativeMonoid : virtual public VirtualMonoid<U> , public MultiplicativeMagma<U> , public PointedSet<U> { public: inline MultiplicativeMonoid( const U& e_U ); }; 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 ); }; 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>( m_U ) , PointedSet<U>( e_U ) {} 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 ); inline U Transfer( const U& 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>( m_U , e_U ) , AbstractNSet<U,I_U>( i_U ) {} template <typename U , typename M_U , typename I_U> inline U AbstractGroup<U,M_U,I_U>::Transfer( const U& u ) { return this->m_i_U( u ); } template <typename U> inline U AdditiveGroup<U>::Transfer( const U& u ) { return -u; } // Enumeration:N->R1-->TとEnumeration_inv:T->R2-->Nは互いに逆写像である仮想関数。 template <typename T , typename R1 , typename R2 , typename E> class VirtualGraph : virtual public UnderlyingSet<T> { public: virtual R1 Enumeration( const int& i ) = 0; inline R2 Enumeration_inv( const T& t ); template <typename PATH> inline R2 Enumeration_inv( const PATH& p ); inline void Reset(); virtual const int& size() const noexcept = 0; virtual E& edge() noexcept = 0; virtual ret_t<E,T> Edge( const T& t ) = 0; private: virtual R2 Enumeration_inv_Body( const T& t ) = 0; }; template <typename T , typename R1 , typename R2 , typename E> class EdgeImplimentation : virtual public VirtualGraph<T,R1,R2,E> { private: int m_size; // 配列への参照を返す関数オブジェクトを構築して返す関数の返り値などの右辺値を受け取ることを // 許容したいので左辺値参照にはしない。 E m_edge; public: inline EdgeImplimentation( const int& size , E edge ); inline const int& size() const noexcept; inline E& edge() noexcept; inline ret_t<E,T> Edge( const T& t ); }; template <typename E> class Graph : public EdgeImplimentation<int,const int&,const int&,E> { public: inline Graph( const int& size , E edge ); inline const int& Enumeration( const int& i ); template <typename F> inline Graph<F> GetGraph( F edge ) const; private: inline const int& Enumeration_inv_Body( const int& t ); }; template <typename T , typename Enum_T , typename Enum_T_inv , typename E> class EnumerationGraph : public EdgeImplimentation<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 ); template <typename F> inline EnumerationGraph<T,Enum_T,Enum_T_inv,F> GetGraph( F edge ) const; private: inline ret_t<Enum_T_inv,T> Enumeration_inv_Body( const T& t ); }; 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(declval<Enum_T>()(0)),Enum_T,Enum_T_inv,E>; // 推論補助のためにE::operator()はデフォルト引数が必要。 template <typename T , typename E> class MemorisationGraph : public EdgeImplimentation<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 void Reset(); template <typename F> inline MemorisationGraph<T,F> GetGraph( F edge ) const; private: inline const int& Enumeration_inv_Body( const T& t ); }; template <typename E> MemorisationGraph( const int& size , E edge ) -> MemorisationGraph<decldecay_t(declval<E>()().back()),E>; 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 EdgeImplimentation<T,R1,R2,E>::EdgeImplimentation( const int& size , E edge ) : m_size( 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 ) : EdgeImplimentation<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 ) : EdgeImplimentation<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 ) : EdgeImplimentation<T,T,const int&,E>( size , move( edge ) ) , m_length() , m_memory() , m_memory_inv() { static_assert( is_invocable_v<E> && is_invocable_v<E,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 T , typename R1 , typename R2 , typename E> inline R2 VirtualGraph<T,R1,R2,E>::Enumeration_inv( const T& t ) { return Enumeration_inv_Body( t ); } template <typename T , typename R1 , typename R2 , typename E> template <typename PATH> inline R2 VirtualGraph<T,R1,R2,E>::Enumeration_inv( const PATH& p ) { return Enumeration_inv_Body( get<0>( p ) ); } template <typename E> inline const int& Graph<E>::Enumeration_inv_Body( 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_Body( const T& t ) { return m_enum_T_inv( t ); } template <typename T , typename E> inline const int& MemorisationGraph<T,E>::Enumeration_inv_Body( 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 T , typename R1 , typename R2 , typename E> inline const int& EdgeImplimentation<T,R1,R2,E>::size() const noexcept { return m_size; } template <typename T , typename R1 , typename R2 , typename E> inline E& EdgeImplimentation<T,R1,R2,E>::edge() noexcept { return m_edge; } template <typename T , typename R1 , typename R2 , typename E> inline ret_t<E,T> EdgeImplimentation<T,R1,R2,E>::Edge( const T& t ) { return m_edge( t ); } 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<T,Enum_T,Enum_T_inv,F>( 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<T,F>( this->size() , move( edge ) ); } #define BELLMAN_FORD_BODY( INITIALISE_PREV , SET_PREV ) \ const U& one = m_M.One(); \ const U& infty = this->Infty(); \ assert( one < infty ); \ const int& size = m_G.size(); \ auto&& i_start = m_G.Enumeration_inv( t_start ); \ assert( 0 <= i_start && i_start < size ); \ vector<U> weight( size , infty ) , weight_copy; \ weight[i_start] = one; \ vector<bool> found( size ); \ found[i_start] = true; \ INITIALISE_PREV; \ \ if( path_length == -1 ){ \ \ path_length = min( size - 1 , int( m_edge.size() ) ); \ \ } else { \ \ assert( many_edges ); \ \ } \ \ \ for( int num = 0 ; num < path_length ; num++ ){ \ \ for( auto& [i,j,w] : m_edge ){ \ \ if( found[i] ){ \ \ U temp = m_M.Product( weight[i] , w ); \ U& weight_j = weight[j]; \ \ if( temp < weight_j ){ \ \ weight_j = move( temp ); \ found[j] = true; \ SET_PREV; \ \ } \ \ } \ \ } \ \ } \ \ \ vector<bool> valid( size , true ); \ \ for( auto& [i,j,w] : m_edge ){ \ \ valid[i] = valid[i] && ( !found[i] || !( m_M.Product( weight[i] , w ) < weight[j] ) ); \ \ } \ \ vector<int> dfs{}; \ \ for( int i = 0 ; i < size ; i++ ){ \ \ if( !valid[i] ){ \ \ dfs.push_back( i ); \ \ } \ \ } \ \ while( !dfs.empty() ){ \ \ const int i = dfs.back(); \ dfs.pop_back(); \ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); \ \ for( auto& edge_ij : edge_i ){ \ \ auto&& j = m_G.Enumeration_inv( edge_ij.first ); \ \ if( valid[j] ){ \ \ valid[j] = false; \ dfs.push_back( j ); \ \ } \ \ } \ \ } \ // GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。 // 入力の範囲内で要件 // (0) MはUの全順序可換モノイド構造である。 // (1) inftyがE_Gの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。 // が成り立つ場合にのみサポート。 // 単一始点全終点最短経路探索/経路復元なしO(|V_G| |E_G|) // 単一始点全終点最短経路探索/経路復元ありO(|V_G| |E_G|) template <typename T , typename GRAPH , typename U , typename MONOID> class AbstractBellmanFord : public PointedSet<U> { private: GRAPH& m_G; // コンストラクタに引数が必要なMultiplicativeMonoidなどはstaticメンバ関数による // 参照返しがしにくく、コンストラクタの返り値である右辺値を受け取ることを許容したいので // 左辺値参照にはしない。 MONOID m_M; // AbstractDijkstraと違って|E_G|が小さい場合にしか適用しないので // E_Gの前計算を許容する。 vector<tuple<int,int,U>> m_edge; public: AbstractBellmanFord( GRAPH& G , MONOID M , const U& infty ); // 入力の範囲内で要件 // (1) many_edges=trueかつpath_length!=-1ならば、始点からのパスの辺の本数はpath_length以下。 // (2) many_edges=falseならば、path_length=-1。 // を満す場合にのみサポート。 // 「到達可能ならば負の閉路を経由できない」の真偽を格納した配列を第1成分に、 // 「到達可能?負の閉路が存在する?辺の本数path_length以下での最短経路長:最短経路長:infty」を // 格納した配列を第2成分に返す。 tuple<vector<bool>,vector<U>> GetDistance( const T& t_start , const bool& many_edges = true , int path_length = -1 ); // t_finalsに属すとは限らない(注意!)各点に対し // 「到達可能ならば負の閉路を経由できない」の真偽を格納した配列を第1成分に、 // t_finalsに属すとは限らない(注意!)各点に対し // 「到達可能?負の閉路を経由する?辺の本数path_length以下での最短経路長:最短経路長:infty」を // 格納した配列を第2成分に、 // t_finalsに属す各点に対し // 「到達可能かつ負の閉路を経由できない?最短経路:空列」を格納した配列を第3成分に返す。 template <template <typename...> typename V> tuple<vector<bool>,vector<U>,vector<list<T>>> GetPath( const T& t_start , const V<T>& t_finals , const bool& many_edges = true , int path_length = -1 ); // 各点に対し // 「到達可能ならば負の閉路を経由できない」の真偽を格納した配列を第1成分に、 // 各点に対し // 「到達可能?負の閉路を経由する?辺の本数path_length以下での最短経路長:最短経路長:infty」を // 格納した配列を第2成分に、 // 各点に対し // 「到達可能かつ負の閉路を経由できない?最短経路:空列」を格納した配列を第3成分に返す。 tuple<vector<bool>,vector<U>,vector<list<T>>> GetPath( const T& t_start , const bool& many_edges = true , int path_length = -1 ); // AbstractDijkstraに合わせてt_finalが1つの特殊化を用意しても // AbstractPotentialisedDijkstraで特殊化できないので用意しない。 }; template <typename GRAPH , typename U , typename MONOID> AbstractBellmanFord( GRAPH& G , MONOID M , const U& infty ) -> AbstractBellmanFord<inner_t<GRAPH>,GRAPH,U,MONOID>; template <typename T , typename GRAPH> class BellmanFord : public AbstractBellmanFord<T,GRAPH,ll,AdditiveMonoid<>> { public: inline BellmanFord( GRAPH& G ); }; template <typename GRAPH> BellmanFord( GRAPH& G ) -> BellmanFord<inner_t<GRAPH>,GRAPH>; template <typename T , typename GRAPH , typename U , typename MONOID> AbstractBellmanFord<T,GRAPH,U,MONOID>::AbstractBellmanFord( GRAPH& G , MONOID M , const U& infty ) : PointedSet<U>( infty ) , m_G( G ) , m_M( move( M ) ) , m_edge() { static_assert( is_same_v<T,inner_t<GRAPH>> && is_same_v<U,inner_t<MONOID>> && !is_same_v<U,int> ); const int& size = m_G.size(); for( int i = 0 ; i < size ; i++ ){ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); for( auto& edge_ij : edge_i ){ m_edge.push_back( { i , m_G.Enumeration_inv( get<0>( edge_ij ) ) , get<1>( edge_ij ) } ); } } } template <typename T , typename GRAPH> inline BellmanFord<T,GRAPH>::BellmanFord( GRAPH& G ) : AbstractBellmanFord<T,GRAPH,ll,AdditiveMonoid<>>( G , AdditiveMonoid<>() , 4611686018427387904 ) {} template <typename T , typename GRAPH , typename U , typename MONOID> tuple<vector<bool>,vector<U>> AbstractBellmanFord<T,GRAPH,U,MONOID>::GetDistance( const T& t_start , const bool& many_edges , int path_length ) { BELLMAN_FORD_BODY( , ); return { move( valid ) , move( weight ) }; } template <typename T , typename GRAPH , typename U , typename MONOID> template <template <typename...> typename V> tuple<vector<bool>,vector<U>,vector<list<T>>> AbstractBellmanFord<T,GRAPH,U,MONOID>::GetPath( const T& t_start , const V<T>& t_finals , const bool& many_edges , int path_length ) { BELLMAN_FORD_BODY( vector<int> prev( size ) , prev[j] = i ); vector<list<T>> path{}; const int path_size = t_finals.size(); path.reserve( path_size ); for( auto& t_final : t_finals ){ list<T> path_j{}; path_j.push_back( t_final ); int i = m_G.Enumeration_inv( t_final ); if( found[i] && valid[i] ){ while( i != i_start ){ i = prev[i]; path_j.push_front( m_G.Enumeration( i ) ); } } path.push_back( path_j ); } return { move( valid ) , move( weight ) , move( path ) }; } template <typename T , typename GRAPH , typename U , typename MONOID> tuple<vector<bool>,vector<U>,vector<list<T>>> AbstractBellmanFord<T,GRAPH,U,MONOID>::GetPath( const T& t_start , const bool& many_edges , int path_length ) { const int& size = m_G.size(); vector<T> t_finals( size ); for( int i = 0 ; i < size ; i++ ){ t_finals[i] = i; } return GetPath( t_start , t_finals ); } #define DIJKSTRA_PREP( INITIALISE_PREV ) \ const U& one = m_M.One(); \ assert( one < infty ); \ auto&& i_start = m_G.Enumeration_inv( t_start ); \ assert( 0 <= i_start && i_start < size ); \ INITIALISE_PREV; \ #define DIJKSTRA_BODY_1( SET_PREV ) \ if( path_length == -1 ){ \ \ path_length = size - 1; \ \ } \ \ weight[i_start] = one; \ int i = i_start; \ \ for( int num = 0 ; num < path_length ; num++ ){ \ \ const U& weight_i = weight[i]; \ fixed[i] = true; \ 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 ); \ \ if( !fixed[j] ){ \ \ const U& edge_ij = get<1>( *itr ); \ U temp = m_M.Product( weight_i , edge_ij ); \ assert( temp < infty ); \ U& weight_j = weight[j]; \ \ if( temp < weight_j ){ \ \ SET_PREV; \ weight_j = move( temp ); \ \ } \ \ } \ \ } \ \ U temp = infty; \ \ for( int j = 0 ; j < size ; j++ ){ \ \ if( !fixed[j] ){ \ \ U& weight_j = weight[j]; \ \ if( weight_j < temp ){ \ \ temp = weight_j; \ i = j; \ \ } \ \ } \ \ } \ \ } \ #define DIJKSTRA_BODY_2( CHECK_FINAL , SET_PREV ) \ assert( path_length == -1 ); \ set<pair<U,int>> vertex{}; \ vertex.insert( pair<U,int>( weight[i_start] = one , i_start ) ); \ \ while( ! vertex.empty() ){ \ \ auto begin = vertex.begin(); \ auto [weight_i,i] = *begin; \ CHECK_FINAL; \ fixed[i] = true; \ vertex.erase( begin ); \ auto&& edge_i = m_G.Edge( m_G.Enumeration( i ) ); \ vector<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( !fixed[j] ){ \ \ const U& edge_ij = get<1>( *itr ); \ U temp = m_M.Product( weight_i , edge_ij ); \ assert( temp < infty ); \ U& weight_j = weight[j]; \ \ if( temp < weight_j ){ \ \ 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& v : changed_vertex ){ \ \ vertex.insert( v ); \ \ } \ \ } \ #define DIJKSTRA_BODY( INITIALISE_PREV , CHECK_FINAL , SET_PREV ) \ DIJKSTRA_PREP( INITIALISE_PREV ); \ \ if( many_edges ){ \ \ DIJKSTRA_BODY_1( SET_PREV ); \ \ } else { \ \ DIJKSTRA_BODY_2( CHECK_FINAL , SET_PREV ); \ \ } \ // GRAPHはグラフG=(V_G,E_G:T->(T \times U)^{< \omega})に相当する型。 // 入力の範囲内で要件 // (0) Mは全順序可換モノイド構造である。 // (1) E_Gの値の各成分の第2成分がM.One()以上である。 // (2) inftyがE_Gの値の各成分の第2成分|V_G|個以下の和で表せるいかなる数よりも大きい。 // が成り立つ場合にのみサポート。 // 単一始点単一終点最短経路探索/経路復元なしO(min(|V_G|^2+|E_G|),(|V_G|+|E_G|)log |E_G|)) // 単一始点単一終点最短経路探索/経路復元ありO(min(|V_G|^2+|E_G|),(|V_G|+|E_G|)log |E_G|)) // 単一始点全終点最短経路探索/経路復元なしO(min(|V_G|^2+|E_G|),(|V_G|+|E_G|)log |E_G|)) // 単一始点全終点最短経路探索/経路復元ありO(|V_G|^2+|E_G|) template <typename T , typename GRAPH , typename U , typename COMM_MONOID> class AbstractDijkstra : public PointedSet<U> { private: GRAPH& m_G; // コンストラクタに引数が必要なMultiplicativeMonoidなどはstaticメンバ関数による // 参照返しがしにくく、コンストラクタの返り値である右辺値を受け取ることを許容したいので // 左辺値参照にはしない。 COMM_MONOID m_M; public: inline AbstractDijkstra( GRAPH& G , COMM_MONOID M , const U& infty ); // 入力の範囲内で要件 // (1) many_edges=trueかつpath_length!=-1ならば、始点からのパスの辺の本数はpath_length以下。 // (2) many_edges=falseならば、path_length=-1。 // を満す場合にのみサポート。 // 経路が存在する場合は最短径路長を、存在しない場合はinftyを返す。 U GetDistance( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , const bool& many_edges = true , int path_length = -1 ); vector<U> GetDistance( const inner_t<GRAPH>& t_start , const bool& many_edges = true , int path_length = -1 ); // 最短経路長の確定している点集合をfixedで指定し、weightに既に格納されている値を重みとする // t_startからの有向辺を追加した時の最短経路長を格納し直す。 void SetDistance( vector<U>& weight , vector<bool>& fixed , const inner_t<GRAPH>& t_start , const bool& many_edges = true , int path_length = -1 ); // 経路が存在する場合は最短径路長を、存在しない場合はinftyを第1成分に、 // 経路が存在する場合は最短径路を、存在しない場合は空列を第2成分に返す。 pair<U,list<inner_t<GRAPH>>> GetPath( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , const bool& many_edges = true , int path_length = -1 ); // t_finalsに属すとは限らない(注意!)各点に対し // 「経路が存在する?最短径路長:infty」を格納した配列を第1成分に、 // t_finalsに属す各点に対し // 「経路が存在する?最短径路:空列」を格納した配列を第2成分に返す。 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 , const bool& many_edges = true , int path_length = -1 ); // 各点に対し「経路が存在する?最短径路長:infty」を格納した配列を第1成分に、 // 各点に対し「経路が存在する?最短径路:空列」を格納した配列を第2成分に返す。 pair<vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start , const bool& many_edges = true , int path_length = -1 ); }; template <typename GRAPH , typename U , typename COMM_MONOID> AbstractDijkstra( GRAPH& G , COMM_MONOID M , const U& infty ) -> AbstractDijkstra<inner_t<GRAPH>,GRAPH,U,COMM_MONOID>; template <typename T , typename GRAPH> class Dijkstra : public AbstractDijkstra<T,GRAPH,ll,AdditiveMonoid<>> { public: inline Dijkstra( GRAPH& G ); }; template <typename GRAPH> Dijkstra( GRAPH& G ) -> Dijkstra<inner_t<GRAPH>,GRAPH>; template <typename T , typename GRAPH , typename U , typename COMM_MONOID> inline AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::AbstractDijkstra( GRAPH& G , COMM_MONOID M , const U& infty ) : PointedSet<U>( infty ) , m_G( G ) , m_M( move( M ) ) { static_assert( ! is_same_v<U,int> ); } template <typename T , typename GRAPH> inline Dijkstra<T,GRAPH>::Dijkstra( GRAPH& G ) : AbstractDijkstra<T,GRAPH,ll,AdditiveMonoid<>>( G , AdditiveMonoid<>() , 4611686018427387904 ) {} template <typename T , typename GRAPH , typename U , typename COMM_MONOID> U AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::GetDistance( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , const bool& many_edges , int path_length ) { const int& size = m_G.size(); const U& infty = this->Infty(); vector weight( size , infty ); vector<bool> fixed( size ); auto&& i_final = m_G.Enumeration_inv( t_final ); DIJKSTRA_BODY( , if( i == i_final ){ break; } , ); U answer{ move( weight[i_final] ) }; return answer; } template <typename T , typename GRAPH , typename U , typename COMM_MONOID> vector<U> AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::GetDistance( const inner_t<GRAPH>& t_start , const bool& many_edges , int path_length ) { const int& size = m_G.size(); const U& infty = this->Infty(); vector weight( size , infty ); vector<bool> fixed( size ); DIJKSTRA_BODY( , , ); return weight; } template <typename T , typename GRAPH , typename U , typename COMM_MONOID> void AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::SetDistance( vector<U>& weight , vector<bool>& fixed , const inner_t<GRAPH>& t_start , const bool& many_edges , int path_length ) { const int& size = m_G.size(); const U& infty = this->Infty(); assert( int( weight.size() ) == size ); assert( int( fixed.size() ) == size ); DIJKSTRA_BODY( , , ); return; } template <typename T , typename GRAPH , typename U , typename COMM_MONOID> pair<U,list<inner_t<GRAPH>>> AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::GetPath( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , const bool& many_edges , int path_length ) { const int& size = m_G.size(); const U& infty = this->Infty(); vector weight( size , infty ); vector<bool> fixed( size ); 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( weight[i] != infty ){ while( i != i_start ){ i = prev[i]; path.push_front( m_G.Enumeration( i ) ); } } U answer{ move( weight[i_final] ) }; return { move( answer ) , move( path ) }; } template <typename T , typename GRAPH , typename U , typename COMM_MONOID> template <template <typename...> typename V> pair<vector<U>,vector<list<inner_t<GRAPH>>>> AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::GetPath( const inner_t<GRAPH>& t_start , const V<inner_t<GRAPH>>& t_finals , const bool& many_edges , int path_length ) { const int& size = m_G.size(); const U& infty = this->Infty(); vector weight( size , infty ); vector<bool> fixed( size ); 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( weight[i] != infty ){ while( i != i_start ){ i = prev[i]; path_j.push_front( m_G.Enumeration( i ) ); } } path.push_back( path_j ); } return { move( weight ) , move( path ) }; } template <typename T , typename GRAPH , typename U , typename COMM_MONOID> pair<vector<U>,vector<list<inner_t<GRAPH>>>> AbstractDijkstra<T,GRAPH,U,COMM_MONOID>::GetPath( const inner_t<GRAPH>& t_start , const bool& many_edges , int path_length ) { 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 , many_edges , path_length ); } #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{ 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 { vector( size , 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|個以下の和で表せるいかなる数よりも大きい。 // が成り立つ場合にのみサポート。 // 負辺を含む場合/含まない場合 // 構築O(|V_G| |E_G|)/O(|V_G|) // 単一始点全終点最短経路探索/経路復元なしO((min(|V_G|^2+|E_G|,|V_G|+|E_G|)log |V_G|)) // 単一始点全終点最短経路探索/経路復元ありO(|V_G|^2+|E_G|) template <typename T , typename GRAPH , typename U , typename GROUP , typename On> class AbstractPotentialisedDijkstra : public PointedSet<U> { private: GRAPH& m_G; GROUP m_M; T m_t_start; // どの辺を許容するかを決める関数オブジェクト。 On m_on; // 「全ての辺を許容する場合に始点から負のループに到達可能でない」の真偽。 bool m_valid; // 全ての辺を許容する場合の始点からのコスト。 vector<U> m_potential; 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 , On on , const bool& valid , vector<U> potential ); inline const bool& Valid() const noexcept; inline const vector<U>& Potential() const noexcept; inline void SetPotential( const bool& valid , vector<U> potential ); // 「到達可能かつ負の閉路を経由できない」の真偽を格納した配列を第1成分に、 // 「到達可能?負の閉路が存在する?辺の本数path_length以下での最短経路長:最短経路長:infty」を // 格納した配列を第2成分に返す。 template <typename...Args> tuple<vector<bool>,vector<U>> GetDistance( Args&&... args ); // 「到達可能かつ負の閉路を経由できない」の真偽を格納した配列を第1成分に、 // 「到達可能?負の閉路を経由する?辺の本数path_length以下での最短経路長:最短経路長:infty」を // 格納した配列を第2成分に、 // 「到達可能かつ負の閉路を経由できない?最短経路:空列」を格納した配列を第3成分に返す。 template <typename...Args> tuple<vector<bool>,vector<U>,vector<list<T>>> GetPath( Args&&... args ); // 返り値の都合、t_finalが1つである特殊化は存在せず、配列化したt_finalsを渡す。 }; template <typename T , typename GRAPH , typename On> class PotentialisedDijkstra : public AbstractPotentialisedDijkstra<T,GRAPH,ll,AdditiveGroup<>,On> { public: template <typename...Args> inline PotentialisedDijkstra( GRAPH& G , const T& t_start , On on , Args&&... args ); }; template <typename T , typename GRAPH , typename U , typename GROUP , typename On> inline AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::AbstractPotentialisedDijkstra( GRAPH& G , GROUP M , const T& t_start , const U& infty , On on , const bool& negative ) : AbstractPotentialisedDijkstra( G , move( M ) , t_start , infty , move( on ) , true , vector<U>() ) { 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_full = m_G.GetGraph( move( edge ) ); AbstractBellmanFord bf{ G_full , m_M , infty }; auto [valid,potential] = bf.GetDistance( m_t_start ); const int& size = m_G.size(); for( int i = 0 ; i < size ; i++ ){ m_valid &= valid[i]; } m_potential = move( potential ); } else { m_potential = vector<U>( m_G.size() , m_M.Zero() ); } } template <typename T , typename GRAPH , typename U , typename GROUP , typename On> inline AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::AbstractPotentialisedDijkstra( GRAPH& G , GROUP M , const T& t_start , const U& infty , On on , const bool& valid , vector<U> potential ) : PointedSet<U>( infty ) , m_G( G ) , m_M( move( M ) ) , m_t_start( t_start ) , m_on( move( on ) ) , m_valid( valid ) , m_potential( potential ) { 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 , On on , Args&&... args ) : AbstractPotentialisedDijkstra<T,GRAPH,ll,AdditiveGroup<>,On>( G , AdditiveGroup<>() , t_start , 4611686018427387904 , move( on ) , forward<decay_t<Args>>( args )... ) {} template <typename T , typename GRAPH , typename U , typename GROUP , typename On> inline const bool& AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::Valid() const noexcept { return m_valid; } template <typename T , typename GRAPH , typename U , typename GROUP , typename On> inline const vector<U>& AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::Potential() const noexcept { return m_potential; } template <typename T , typename GRAPH , typename U , typename GROUP , typename On> inline void AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,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 U , typename GROUP , typename On> template <typename...Args> tuple<vector<bool>,vector<U>> AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::GetDistance( Args&&... args ) { POTENTIALISED_DIJKSTRA_BODY( GetDistance( m_t_start , forward<Args>( args )... ) , value , move( value ) ); } template <typename T , typename GRAPH , typename U , typename GROUP , typename On> template <typename...Args> tuple<vector<bool>,vector<U>,vector<list<T>>> AbstractPotentialisedDijkstra<T,GRAPH,U,GROUP,On>::GetPath( Args&&... args ) { POTENTIALISED_DIJKSTRA_BODY( GetPath( m_t_start , forward<Args>( args )... ) , get<0>( value ) , move( get<0>( value ) ) , move( get<1>( value ) ) ); } // AAA ライブラリは以上に挿入する。 #define INCLUDE_MAIN #include __FILE__ #else // INCLUDE_LIBRARY #ifdef DEBUG #define _GLIBCXX_DEBUG #define SIGNAL signal( SIGABRT , &AlertAbort ); #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 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 SIGNAL #define DEXPR( LL , BOUND , VALUE , DEBUG_VALUE ) CEXPR( LL , BOUND , VALUE ) #define ASSERT( A , MIN , MAX ) assert( ( MIN ) <= A && A <= ( MAX ) ) #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 , ... ) string __VA_ARGS__; VariadicGetline( cin , SEPARATOR , __VA_ARGS__ ) #define GETLINE( ... ) GETLINE_SEPARATE( '\n' , __VA_ARGS__ ) #else #define SET_LL( A ) cin >> A #define CIN( LL , ... ) LL __VA_ARGS__; VariadicCin( cin , __VA_ARGS__ ) #define SET_A( A , N ) 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; #define REPEAT_MAIN( BOUND ) int main(){ ios_base::sync_with_stdio( false ); cin.tie( nullptr ); SIGNAL; DEXPR( int , bound_test_case_num , BOUND , min( BOUND , 100 ) ); int test_case_num = 1; if constexpr( bound_test_case_num > 1 ){ SET_ASSERT( test_case_num , 1 , bound_test_case_num ); } 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 CEXPR( LL , BOUND , VALUE ) constexpr LL BOUND = VALUE #define SET_ASSERT( A , MIN , MAX ) SET_LL( A ); ASSERT( A , MIN , MAX ) #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( ... ) COUT( __VA_ARGS__ ); return // 型のエイリアス #define decldecay_t( VAR ) decay_t<decltype( VAR )> template <typename F , typename...Args> using ret_t = decltype( declval<F>()( declval<Args>()... ) ); template <typename T> using inner_t = typename T::type; 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>; // 入出力用 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( bool& auto_checked ); #endif #define INCLUDE_LIBRARY #include __FILE__ #endif // INCLUDE_LIBRARY #endif // INCLUDE_MAIN