求出 bcc 后再……根据大白书上的思路即可。
然后我用的是自定义的 stack 类模板:
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 //#include<stack> 5 #include<stdexcept> 6 #include<algorithm> 7 using namespace std; 8 typedef long long LL; 9 const int N = 50003; 10 11 template <typename T, size_t SIZE = N> 12 class stack { 13 T *val; 14 size_t tot; 15 size_t limit; 16 public: 17 stack(size_t limit = SIZE): limit(limit) { 18 val = (T*)malloc(sizeof(T) * limit); 19 tot = 0; 20 } 21 stack(const stack<T> &s2): limit(s2.limit), tot(s2.tot) { 22 val = (T*)malloc(sizeof(T) * limit); 23 for(size_t i = 0; i < tot; ++i) 24 val[i] = s2.val[i]; 25 } 26 stack& operator = (const stack<T> &s2) { 27 tot = s2.tot; 28 limit = s2.limit; 29 T *temp = (T*)malloc(sizeof(T) * s2.limit); 30 for(size_t i = 0; i < s2.tot; ++i) 31 temp[i] = s2.val[i]; 32 free(val); 33 this->val = temp; 34 } 35 void push(const T &x) { 36 if(tot == limit) { 37 stack<T> temp(*this); 38 free(val); 39 val = (T*)malloc(sizeof(T) * (limit <<= 1)); 40 for(size_t i = 0; i < temp.tot; ++i) 41 val[i] = temp.val[i]; 42 } 43 val[tot++] = x; 44 } 45 void pop() { 46 if(tot == 0) throw out_of_range("Stack less flow at Stack<T>::pop()"); 47 --tot; 48 } 49 T top() const { 50 if(tot == 0) throw out_of_range("Stack less flow at Stack<T>::top()"); 51 return val[tot - 1]; 52 } 53 size_t size() const { return tot; } 54 bool empty() const { return tot == 0; } 55 void clear() { tot = 0; } 56 ~stack() { free(val); } 57 }; 58 59 60 struct Edge { 61 int u,v; 62 Edge(int u, int v): u(u), v(v) {} 63 }; 64 65 vector<int> g[N], bcc[N]; 66 int pre[N], iscut[N], bccno[N], dfs_clock, bcc_cnt; 67 stack<Edge, N> s; 68 69 int dfs(int u, int fa) { 70 int lowu = pre[u] = ++dfs_clock; 71 int child = 0; 72 for(int i = 0; i < g[u].size(); ++i) { 73 int v = g[u][i]; 74 Edge e = Edge(u,v); 75 if(!pre[v]) { 76 s.push(e); 77 ++child; 78 int lowv = dfs(v,u); 79 lowu = min(lowu, lowv); 80 if(lowv >= pre[u]) { 81 iscut[u] = 1; 82 ++bcc_cnt; 83 bcc[bcc_cnt].clear(); 84 while(1) { 85 Edge x = s.top(); s.pop(); 86 if(bccno[x.u] != bcc_cnt) { 87 bccno[x.u] = bcc_cnt; 88 bcc[bcc_cnt].push_back(x.u); 89 } 90 if(bccno[x.v] != bcc_cnt) { 91 bccno[x.v] = bcc_cnt; 92 bcc[bcc_cnt].push_back(x.v); 93 } 94 if(x.u == u && x.v == v) break; 95 } 96 } 97 } 98 else if(pre[v] < pre[u] && v != fa) { 99 lowu = min(lowu, pre[v]); 100 s.push(e); 101 } 102 } 103 if(fa < 0 && child == 1) iscut[u] = 0; 104 return lowu; 105 } 106 107 void find_bcc(int n) { 108 memset(pre, 0, sizeof pre); 109 memset(iscut, 0, sizeof iscut); 110 memset(bccno, 0, sizeof bccno); 111 dfs_clock = bcc_cnt = 0; 112 for(int i = 0; i < n; ++i) 113 if(!pre[i]) dfs(i, -1); 114 } 115 116 int main() { 117 int n,x,y,Case = 0, maxn = 1; 118 while(~scanf("%d",&n),n) { 119 for(int i = 0; i <= maxn; ++i) 120 g[i].clear(); 121 maxn = 1; 122 for(int i = 0; i < n; ++i) { 123 scanf("%d %d",&x,&y); 124 maxn = max(maxn, x); 125 maxn = max(maxn, y); 126 g[x].push_back(y); 127 g[y].push_back(x); 128 } 129 find_bcc(maxn + 1); 130 LL ans1 = 0, ans2 = 1; 131 for(int i = 1; i <= bcc_cnt; ++i) { 132 int cut = 0; 133 for(int j = 0; j < bcc[i].size(); ++j) 134 if(iscut[bcc[i][j]]) ++cut; 135 if(cut == 1) { 136 ++ans1; 137 ans2 *= bcc[i].size() - cut; 138 } 139 } 140 if(bcc_cnt == 1) { 141 ans1 = 2; 142 ans2 = (LL)bcc[1].size() * (bcc[1].size() - 1) / 2; 143 } 144 printf("Case %d: %lld %lld\n",++Case, ans1, ans2); 145 } 146 return 0; 147 }