voiddfs_siz( int u, int p ){ vis[u] = true; siz[u] = ( u <= n ); for( int v : tree[u] ) { if( v == p ) continue; dfs_siz( v, u ); siz[u] += siz[v]; } }
voiddfs_calc( int u, int p, ll all ){ ll cnt = 0; ll pre = all - siz[u]; for( int v : tree[u] ) { if( v == p ) continue; cnt += 2ll * pre * siz[v]; pre += siz[v]; dfs_calc( v, u, all ); } if( u <= n ) cnt += 2ll * ( all - 1 ); ans += weight[u] * cnt; }
voidsolve( ){ n = read( ); int m = read( ); for( int i = 1; i <= m; ++ i ) { int u = read( ), v = read( ); add_edge( u, v, i ); }
for( int i = 1; i <= n; ++ i ) { if( !dfn[i] ) top = 0, tarjan( i, 0 ); }
int tot = n + vcnt; for( int i = 1; i <= tot; ++ i ) { tree[i].clear( ); } for( int id = 1; id <= vcnt; ++ id ) { int block = n + id; for( int u : comp[id] ) { tree[block].push_back( u ); tree[u].push_back( block ); } }
for( int u = 1; u <= n; ++ u ) { weight[u] = -1; }
for( int id = 1; id <= vcnt; ++ id ) { weight[n + id] = comp[id].size( ); }
for( int i = 1; i <= n; ++ i ) { if( vis[i] ) continue; dfs_siz( i, 0 ); dfs_calc( i, 0, siz[i] ); }