有M条边,告诉你u、v两点有一条无向边,然后点是所有输入点的最大值,现在问如果有任意一个点被删除了,要保证剩下的点都有办法走到出口,所需要的最少建设的出口通道是几个?并且输出方案数。
很明显一点,如果某个强连通子图没有割点的话,那么说明这个子图==该联通子图,那么只需要从其中所有的点随便选两个点作为出口点即可,方案数为C(N, 2),需要加的点是2个。
如果,存在一个强连通子图,它有且只有一个割点,那么需要从它内的V-1个点中(排除那个割点)选一个点作为出口点,如果割的不是割点,那么其余点就可以通过走割点方向走出去,如果是割点的话,那个其余点就走这个点走出去。
如果存在一个强连通子图,它有多个割点(≥2),那么他就不需要再新建点了,它可以从没有被删除的割点方向找到出路。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <string> 5 #include <cstring> 6 #include <algorithm> 7 #include <limits> 8 #include <vector> 9 #include <stack> 10 #include <queue> 11 #include <set> 12 #include <map> 13 #include <bitset> 14 #include <unordered_map> 15 #include <unordered_set> 16 #define lowbit(x) ( x&(-x) ) 17 #define pi 3.141592653589793 18 #define e 2.718281828459045 19 #define INF 0x3f3f3f3f 20 #define HalF (l + r)>>1 21 #define lsn rt<<1 22 #define rsn rt<<1|1 23 #define Lson lsn, l, mid 24 #define Rson rsn, mid+1, r 25 #define QL Lson, ql, qr 26 #define QR Rson, ql, qr 27 #define myself rt, l, r 28 #define pii pair<int, int> 29 #define MP(a, b) make_pair(a, b) 30 using namespace std; 31 typedef unsigned long long ull; 32 typedef unsigned int uit; 33 typedef long long ll; 34 const int maxN = 1e3 + 7; 35 int N, M, head[maxN], cnt; 36 struct Eddge 37 { 38 int nex, to; 39 Eddge(int a=-1, int b=0):nex(a), to(b) {} 40 }edge[maxN << 1]; 41 bool vis[maxN << 1] = {false}; 42 void addEddge(int u, int v) 43 { 44 edge[cnt] = Eddge(head[u], v); vis[cnt] = false; 45 head[u] = cnt++; 46 } 47 inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); } 48 int dfn[maxN], low[maxN], tot = 0, Stap[maxN], Stop, Bcnt, Bhave_cut[maxN] = {0}; 49 bool iscut[maxN] = {false}; 50 vector<int> Bt[maxN], V; 51 void Tarjan(int u, int fa) 52 { 53 int child = 0; 54 V.push_back(u); 55 dfn[u] = low[u] = ++tot; 56 Stap[++Stop] = u; 57 for(int i=head[u], v; ~i; i=edge[i].nex) 58 { 59 if(vis[i]) continue; 60 vis[i] = vis[i ^ 1] = true; 61 v = edge[i].to; 62 if(!dfn[v]) 63 { 64 child++; 65 Tarjan(v, u); 66 low[u] = min(low[u], low[v]); 67 if(low[v] >= dfn[u]) 68 { 69 iscut[u] = true; 70 int p; Bcnt++; Bt[Bcnt].clear(); Bhave_cut[Bcnt] = 0; 71 do 72 { 73 p = Stap[Stop--]; 74 Bt[Bcnt].push_back(p); 75 } while(p ^ v); 76 Bt[Bcnt].push_back(u); 77 } 78 } 79 else low[u] = min(low[u], dfn[v]); 80 } 81 if(!fa && child == 1) iscut[u] = false; 82 } 83 inline void init() 84 { 85 cnt = tot = Bcnt = Stop = 0; 86 memset(dfn, 0, sizeof(dfn)); 87 memset(iscut, false, sizeof(iscut)); 88 memset(head, -1, sizeof(head)); 89 } 90 int main() 91 { 92 int Cas = 0; 93 while(scanf("%d", &M) && M) 94 { 95 init(); N = 0; 96 for(int i=1, u, v; i<=M; i++) 97 { 98 scanf("%d%d", &u, &v); N = max(N, max(u, v)); 99 _add(u, v); 100 } 101 ull ans_num = 0, ans_sum = 1; 102 for(int i=1, len, cnum; i<=N; i++) 103 { 104 if(!dfn[i]) 105 { 106 V.clear(); 107 Bcnt = 0; 108 Tarjan(i, 0); 109 len = (int)V.size(); 110 cnum = 0; 111 for(int j=0; j<len; j++) 112 { 113 if(iscut[V[j]]) cnum++; 114 } 115 if(!cnum) 116 { 117 ans_num += 2; 118 ans_sum *= 1LL * len * (len - 1) / 2; 119 } 120 else 121 { 122 for(int j=1; j<=Bcnt; j++) 123 { 124 for(int v : Bt[j]) if(iscut[v]) Bhave_cut[j]++; 125 if(Bhave_cut[j] == 1) 126 { 127 ans_num++; 128 ans_sum *= (Bt[j].size() - 1); 129 } 130 } 131 } 132 } 133 } 134 printf("Case %d: %llu %llu\n", ++Cas, ans_num, ans_sum); 135 } 136 return 0; 137 }