1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
| struct Edge { int id, v; ll w; }; vector<Edge> adj[maxn]; vector<int> comp[maxn];
int dfn[maxn], low[maxn], timer; int stk[maxn], top;
bool cut[maxn]; int vcnt;
void add_edge( int u, int v, ll w, int id ) { adj[u].push_back({ id, v, w }); adj[v].push_back({ id, u, w }); }
void tarjan( int u, int in_edge ) { dfn[u] = low[u] = ++ timer; stk[++ top] = u; int child = 0; for( auto [id, v, w] : adj[u] ) { if( !dfn[v] ) { child ++; tarjan( v, id ); low[u] = min( low[u], low[v] ); if( low[v] >= dfn[u] ) { if( in_edge || child >= 2 ) { cut[u] = true; } vcnt ++; comp[vcnt].push_back( u ); int x; do { x = stk[top --]; comp[vcnt].push_back( x ); } while( x != v ); } } else if( id != in_edge ) { low[u] = min( low[u], dfn[v] ); } } if( !in_edge && child == 0 ) { ++ vcnt; comp[vcnt].push_back( u ); -- top; } }
bool exist[maxn]; vector<int> ver; int Case = 1;
void solve( int edges ) { if( edges == 0 ) return; ver.clear( ); timer = top = vcnt = 0; for( int i = 1; i < maxn; ++ i ) { adj[i].clear( ); comp[i].clear( ); dfn[i] = low[i] = 0; cut[i] = exist[i] = 0; }
for( int i = 1; i <= edges; ++ i ) { int u = read( ), v = read( ); add_edge( u, v, 0, i ); if( !exist[u] ) { exist[u] = 1; ver.push_back( u ); } if( !exist[v] ) { exist[v] = 1; ver.push_back( v ); } }
for( int u : ver ) { if( !dfn[u] ) tarjan( u, 0 ), top = 0; }
int ans = 0; ull ways = 1;
for( int u = 1; u <= vcnt; ++ u ) { int ccnt = 0; int ocnt = 0; for( int v : comp[u] ) { if( cut[v] ) ++ ccnt; else ++ ocnt; }
if( ccnt == 0 ) { ans += 2; ways *= 1ull * ocnt * ( ocnt - 1 ) / 2; } else if( ccnt == 1 ) { ans += 1; ways *= ocnt; } } printf( "Case %d: %d %llu\n", Case++, ans, ways ); }
|