// 誤解法(オーバーフロー)チェックその1 #ifndef INCLUDE_MODE #define INCLUDE_MODE // #define REACTIVE // #define USE_GETLINE #endif #ifdef INCLUDE_MAIN inline void Solve() { DEXPR( int , bound , 1e5 , 10 ); CIN_ASSERT( N , 2 , bound ); CIN_ASSERT( M , 1 , bound ); gE.resize( N ); UnionFindForest uff{ uint( N ) }; unordered_map> W[N]; FOR( j , 0 , M ){ CIN_ASSERT( uj , 1 , N ); CIN_ASSERT( vj , 1 , N ); assert( --uj != --vj ); CIN_ASSERT( wj , 0 , bound ); if( uff.Graft( uj , vj , -wj ) ){ gE[uj].push_back( vj ); gE[vj].push_back( uj ); W[uj][vj] = {wj,j}; W[vj][uj] = {-wj,j}; } else { BreadthFirstSearch> bfs{ N , uj }; while( bfs.Next() != vj ){} vector answer{}; answer.push_back( j + 1 ); // ll w = wj; int w = wj; while( uj != vj ){ int uk = bfs.prev( vj ); auto& [wk,k] = W[vj][uk]; answer.push_back( k + 1 ); w += wk; vj = uk; } assert( w != 0 ); int L = answer.size(); COUT( L ); COUT( ++uj ); if( w > 0 ){ COUT_A( answer , L ); } else { FOREQINV( i , L-1 , 0 ){ cout << answer[i] << " \n"[i==0]; } } return; } } RETURN( -1 ); } REPEAT_MAIN(1); #else // INCLUDE_MAIN #ifdef INCLUDE_SUB template list GetgE( const int& i ) { // list answer{}; list answer = gE[i]; // VVV 入力によらない処理は以下に挿入する。 // AAA 入力によらない処理は以上に挿入する。 return answer; } #define INCLUDE_MAIN #include __FILE__ #else // INCLUDE_SUB #ifdef INCLUDE_LIBRARY // https://github.com/p-adic/cpp // VVV ライブラリは以下に挿入する。 // Tが加法について可換群をなす場合にのみサポート。 // - 構築 O(size) // - 一点根取得 O(α(size)) // - 全根取得 O(size) // - 根数取得 O(1) // - 二点符号付き重み取得 O(α(size)) // - 二点接合 O(α(size)) template class UnionFindForest { private: uint m_node_size; uint m_root_size; vector m_pred; vector m_height; // m_w[num]はnum番目のnodeがrootならば0、rootでないならば親nodeへ向かうパスの符号付き重み vector m_w; public: inline UnionFindForest( const uint& size ); // num番目のnodeのrootを計算して返す。 const uint& RootOfNode( const uint& num ); // rootを全て格納する。 template