結果
問題 | No.2915 辺更新価値最大化 |
ユーザー | 👑 p-adic |
提出日時 | 2024-02-10 23:00:59 |
言語 | C++17 (gcc 12.3.0 + boost 1.83.0) |
結果 |
TLE
|
実行時間 | - |
コード長 | 44,766 bytes |
コンパイル時間 | 4,714 ms |
コンパイル使用メモリ | 261,032 KB |
実行使用メモリ | 13,756 KB |
最終ジャッジ日時 | 2024-07-29 20:30:31 |
合計ジャッジ時間 | 11,604 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge5 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
testcase_00 | AC | 2 ms
13,756 KB |
testcase_01 | AC | 2 ms
6,816 KB |
testcase_02 | AC | 2 ms
6,940 KB |
testcase_03 | AC | 2 ms
6,940 KB |
testcase_04 | AC | 2 ms
6,944 KB |
testcase_05 | AC | 2 ms
6,944 KB |
testcase_06 | AC | 2 ms
6,944 KB |
testcase_07 | AC | 65 ms
6,944 KB |
testcase_08 | AC | 67 ms
6,940 KB |
testcase_09 | AC | 71 ms
6,940 KB |
testcase_10 | AC | 69 ms
6,940 KB |
testcase_11 | AC | 70 ms
6,940 KB |
testcase_12 | AC | 70 ms
6,940 KB |
testcase_13 | AC | 253 ms
6,940 KB |
testcase_14 | AC | 298 ms
6,944 KB |
testcase_15 | AC | 485 ms
6,940 KB |
testcase_16 | AC | 1,148 ms
6,944 KB |
testcase_17 | TLE | - |
testcase_18 | -- | - |
testcase_19 | -- | - |
testcase_20 | -- | - |
testcase_21 | -- | - |
testcase_22 | -- | - |
testcase_23 | -- | - |
testcase_24 | -- | - |
testcase_25 | -- | - |
testcase_26 | -- | - |
testcase_27 | -- | - |
ソースコード
// 誤解法(O(V^2)のダイクストラを用いたポテンシャル付きダイクストラ)チェック #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<list<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 ); CEXPR( bool , many_edges , true ); 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; virtual R2 Enumeration_inv( const T& t ) = 0; 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; }; 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 ); 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 : 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 ); 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(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 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(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( enum_T ) , m_enum_T_inv( 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 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 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( 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; // コンストラクタに引数が必要なMultiplicativeMonoidなどはstaticメンバ関数による // 参照返しがしにくく、コンストラクタの返り値である右辺値を受け取ることを許容したいので // 左辺値参照にはしない。 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 , const bool& dummy = true ); 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 , const bool& dummy = true ); tuple<bool,vector<U>,vector<list<inner_t<GRAPH>>>> GetPath( const inner_t<GRAPH>& t_start , const bool& dummy = true ); }; 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( 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>( 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 , const bool& dummy ) { 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 , const bool& dummy ) { 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 bool& dummy ) { 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_PREP( INITIALISE_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 ); \ INITIALISE_PREV; \ #define DIJKSTRA_BODY_1( SET_PREV ) \ weight[i_start] = zero; \ int i = i_start; \ \ for( int num = 0 ; num < size ; num++ ){ \ \ const U& weight_i = weight[i]; \ found[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( !found[j] ){ \ \ const U& edge_ij = get<1>( *itr ); \ U temp = m_M.Sum( 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( !found[j] ){ \ \ U& weight_j = weight[j]; \ \ if( weight_j < temp ){ \ \ temp = weight_j; \ i = j; \ \ } \ \ } \ \ } \ \ } \ #define DIJKSTRA_BODY_2( CHECK_FINAL , SET_PREV ) \ set<pair<U,int>> vertex{}; \ vertex.insert( pair<U,int>( weight[i_start] = zero , i_start ) ); \ \ 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 = get<1>( *itr ); \ U temp = m_M.Sum( 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 itr_changed = changed_vertex.begin() , end_changed = changed_vertex.end() ; itr_changed != end_changed ; itr_changed++ ){ \ \ vertex.insert( *itr_changed ); \ \ } \ \ } \ #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.Zero()以上である。 // (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 GRAPH , typename MONOID , typename U> class AbstractDijkstra : public PointedSet<U> { private: GRAPH& m_G; // コンストラクタに引数が必要なMultiplicativeMonoidなどはstaticメンバ関数による // 参照返しがしにくく、コンストラクタの返り値である右辺値を受け取ることを許容したいので // 左辺値参照にはしない。 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 , const bool& many_edges = true ); vector<U> GetDistance( const inner_t<GRAPH>& t_start , const bool& many_edges = true ); pair<U,list<inner_t<GRAPH>>> GetPath( const inner_t<GRAPH>& t_start , const inner_t<GRAPH>& t_final , const bool& many_edges = true ); 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 ); 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( 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 , const bool& many_edges ) { 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 , const bool& many_edges ) { 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 , const bool& many_edges ) { 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 , const bool& many_edges ) { 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{ 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|個以下の和で表せるいかなる数よりも大きい。 // が成り立つ場合にのみサポート。 // 負辺を含む場合/含まない場合 // 構築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 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 , 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 ); tuple<bool,vector<U>> GetDistance( const bool& many_edges = true ); 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 , On on , 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( 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 ); 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 , 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,AdditiveGroup<>,ll,On>( G , AdditiveGroup<>() , t_start , 4611686018427387904 , move( on ) , 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( const bool& many_edges ) { POTENTIALISED_DIJKSTRA_BODY( GetDistance( m_t_start , many_edges ) , 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 ) ) ); } // 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