標籤:
題意:n條隧道由一些點串連而成,其中每條隧道連結兩個連接點。任意兩個連接點之間最多隻有一條隧道。任務就是在這些連接點中,安裝盡量少的太平井和逃生裝置,使得不管哪個連接點倒塌,工人都能從其他太平井逃脫,求最少安裝數量和方案。
思路:其實本題就相當於在一張無向圖中,塗盡量少的黑點,使得任意刪除哪個點,每個連通分量至少有一個黑點。因為不同的連通分量最多隻有一個公用點,那一定是割點。可以發現,塗黑割點是不划算的,而且在 一個點-雙連通分量中塗黑兩個黑點也是不划算的。所以只有當點-雙連通分量只有一個割點時,才需要塗,而且是任選一個非割點塗黑。
2011年final題,想法不是很好明白,聯絡實際再YY一下就懂了
1 //struct ID 用來減小數位,有點離散的作用。但是注釋掉以後已耗用時間簡短,AC 2 #include<cstdio> 3 #include<stack> 4 #include<vector> 5 #include<map> 6 #include<algorithm> 7 #include<cstring> 8 using namespace std; 9 typedef long long LL; 10 11 struct Edge { 12 int u, v; 13 }; 14 15 const int maxn = 100000 + 10; 16 int pre[maxn], iscut[maxn], bccno[maxn], dfs_clock, bcc_cnt; // 割頂的bccno無意義 17 vector<int> G[maxn], bcc[maxn]; 18 19 stack<Edge> S; 20 21 int dfs(int u, int fa) { 22 int lowu = pre[u] = ++dfs_clock; 23 int child = 0; 24 for(int i = 0; i < G[u].size(); i++) { 25 int v = G[u][i]; 26 Edge e = (Edge) { 27 u, v 28 }; 29 if(!pre[v]) { // 沒有訪問過v 30 S.push(e); 31 child++; 32 int lowv = dfs(v, u); 33 lowu = min(lowu, lowv); // 用後代的low函數更新自己 34 if(lowv >= pre[u]) { 35 iscut[u] = true; 36 bcc_cnt++; 37 bcc[bcc_cnt].clear(); 38 for(;;) { 39 Edge x = S.top(); 40 S.pop(); 41 if(bccno[x.u] != bcc_cnt) { 42 bcc[bcc_cnt].push_back(x.u); 43 bccno[x.u] = bcc_cnt; 44 } 45 if(bccno[x.v] != bcc_cnt) { 46 bcc[bcc_cnt].push_back(x.v); 47 bccno[x.v] = bcc_cnt; 48 } 49 if(x.u == u && x.v == v) break; 50 } 51 } 52 } else if(pre[v] < pre[u] && v != fa) { 53 S.push(e); 54 lowu = min(lowu, pre[v]); // 用反向邊更新自己 55 } 56 } 57 if(fa < 0 && child == 1) iscut[u] = 0; 58 return lowu; 59 } 60 61 //struct ID { 62 // map<int, int> m; 63 // int cnt; 64 // ID():cnt(0) { } 65 // int get(int x) { 66 // if(!m.count(x)) m[x] = cnt++; 67 // return m[x]; 68 // } 69 //}; 70 71 int main() { 72 int kase = 0, n; 73 while(scanf("%d", &n) == 1 && n) { 74 memset(pre, 0, sizeof(pre)); 75 memset(iscut, 0, sizeof(iscut)); 76 memset(bccno, 0, sizeof(bccno)); 77 for(int i = 0; i < n*2; i++) G[i].clear(); 78 dfs_clock = bcc_cnt = 0; 79 80 // ID id; 81 for(int i = 0; i < n; i++) { 82 int u, v; 83 scanf("%d%d", &u, &v); 84 // u = id.get(u); 85 // v = id.get(v); 86 u--; 87 v--; 88 G[u].push_back(v); 89 G[v].push_back(u); 90 } 91 dfs(0, -1); // 調用結束後S保證為空白,所以不用清空 92 93 LL ans1 = 0, ans2 = 1; 94 for(int i = 1; i <= bcc_cnt; i++) { 95 int cut_cnt = 0; 96 for(int j = 0; j < bcc[i].size(); j++) 97 if(iscut[bcc[i][j]]) cut_cnt++; 98 if(cut_cnt == 1) { 99 ans1++;100 ans2 *= (LL)(bcc[i].size() - cut_cnt);101 }102 }103 if(bcc_cnt == 1) {104 ans1 = 2;105 ans2 = bcc[1].size() * (bcc[1].size() - 1) / 2;106 }107 printf("Case %d: %lld %lld\n", ++kase, ans1, ans2);108 }109 return 0;110 }
View Code
UVALive 5135 Mining Your Own Business 雙連通分量 2011final