#ifdef INCLUDE_MAIN inline void Solve() { CIN( ll , N , M ); CIN_A( int , C , N ); UnionFindForest uff( N ); e.resize( N ); FOR( j , 0 , M ){ CIN( int , uj , vj ); uj--; vj--; if( C[uj] == C[vj] ){ uff.Graft( uj , vj ); } } uint answer = 0; uint count[N+1]{}; vector root{}; uff.SetRoot( root ); const uint& size = uff.SizeOfRoot(); FOR( i , 0 , size ){ count[C[root[i]]]++; } FOREQ( i , 1 , N ){ count[i] > 0 ? answer += count[i] - 1 : answer; } RETURN( answer ); } REPEAT_MAIN(1); #else // INCLUDE_MAIN #ifdef INCLUDE_SUB template list E( const int& i ) { // list answer{}; list answer = e[i]; // VVV 入力によらない処理は以下に挿入する。 // AAA 入力によらない処理は以上に挿入する。 return answer; } template inline T F( const T& t ){ return f[t]; } template inline T G( const int& i ){ return g[i]; } ll Naive( int N , int M , int K ) { ll answer = N + M + K; return answer; } ll Answer( ll N , ll M , ll K ) { // START_WATCH; ll answer = N + M + K; // // TLに準じる乱択や全探索。デフォルトの猶予は100.0[ms]。 // CEXPR( double , TL , 2000.0 ); // while( CHECK_WATCH( TL ) ){ // } return answer; } inline void Experiment() { // CEXPR( int , bound , 10 ); // FOREQ( N , 0 , bound ){ // FOREQ( M , 0 , bound ){ // FOREQ( K , 0 , bound ){ // COUT( N , M , K , ":" , Naive( N , M , K ) ); // } // } // // cout << Naive( N ) << ",\n"[N==bound]; // } } inline void SmallTest() { // CEXPR( int , bound , 10 ); // FOREQ( N , 0 , bound ){ // FOREQ( M , 0 , bound ){ // FOREQ( K , 0 , bound ){ // COMPARE( N , M , K ); // } // } // // COMPARE( N ); // } } #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/Utility/VLTree/UnionFindForest/compress.txt */ // VVV 常設でないライブラリは以下に挿入する。 // Tが加法について可換群をなす場合にのみサポート。 // - 構築 O(size) // - 一点根取得 O(α(size)) // - 全根取得 O(rootの個数) // - 根数取得 O(1) // - 二点符号付き重み取得 O(α(size)) // - 二点接合 O(α(size)) template class UnionFindForest { private: uint m_node_size; uint m_root_size; vector m_pred; vector m_length; // m_left_root[0]は左端のroot vector m_left_root; // m_right_root[m_size-1]は右端のroot vector m_right_root; // m_w[num]はnum番目のnodeがrootならば0、rootでないならば親nodeへ向かうパスの符号付き重み vector m_w; public: UnionFindForest( const uint& size ); // num番目のnodeのrootを計算して返す。 const uint& RootOfNode( const uint& num ); // rootを全て格納する。 template