思路:
我们知道删去割点,连通分量数目增加,其中一个点必然是割点,那么另一个点枚举就可以了
我们用cut[v]表示删去这个点 增加的连通分量数目 那么我们只要把求割点的bool数组改成int数组就可以了
这里我们要考虑一下对于根节点,如果是一个孤立节点是一个cc,删去以后没有cc了,那么减少了1,由于cut[v]初始化为0,-1即可
如果不是孤立节点 也要减去本身自己这个cc的1 也要-1
参考code:
// // Created by TaoSama on 2015-06-14 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e4 + 10; int n, m; int head[N], pnt[N], nxt[N], cnt; void add_edge(int u, int v) { pnt[cnt] = v; nxt[cnt] = head[u]; head[u] = cnt++; } int dfn[5005], low[5005], cut[5005], tim; bool in[5005]; void dfs(int u, int f, int del) { dfn[u] = low[u] = ++tim; int son = 0; for(int i = head[u]; ~i; i = nxt[i]) { int &v = pnt[i]; if(v == f || v == del) continue; if(!dfn[v]) { ++son; dfs(v, u, del); low[u] = min(low[u], low[v]); if(low[v] >= dfn[u]) cut[u]++; } else low[u] = min(low[u], dfn[v]); } if(f < 0) cut[u]--; //根节点要-1 孤立节点算1个cc没有儿子0-1 = -1 不是孤立节点的话减少1 总之都要-1 } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(scanf("%d%d", &n, &m) == 2) { cnt = 0; memset(head, -1, sizeof head); for(int i = 0; i < m; ++i) { int u, v; scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } int ans = -INF, cc; for(int i = 0; i < n; ++i) { cc = tim = 0; memset(dfn, 0, sizeof dfn); memset(low, 0, sizeof low); memset(cut, 0, sizeof cut); for(int j = 0; j < n; ++j) { if(i == j) continue; if(!dfn[j]) { ++cc; dfs(j, -1, i); } } for(int j = 0; j < n; ++j) { if(i == j) continue; ans = max(ans, cc + cut[j]); } } printf("%d\n", ans); } return 0; }
Reliable Nets
题意:无向图,找到一个删去任意一条边 还连通的的权和最小的图
思路:由于边数很小,枚举边,判断图是否连通,连通后判断是否只有一个bcc
bcc的定义 任意两点 至少存在两条 边不重复 的路径
1-2-4-5 1-3-4-5 存在相交的路径 说明不在同一个bcc中 那么删掉4-5图就不连通了
参考code:
// // Created by TaoSama on 2015-06-14 // Copyright (c) 2015 TaoSama. All rights reserved. // //#pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <stack> #include <string> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int N = 1e5 + 10; int n, m; int head[50], pnt[50], nxt[50], cost[50], cnt; struct E { int u, v, c; } G[50]; void add_edge(int u, int v, int c) { pnt[cnt] = v; cost[cnt] = c; nxt[cnt] = head[u]; head[u] = cnt++; } int par[20], het[20]; int find(int x) { return par[x] = (par[x] == x ? x : find(par[x])); } bool isConnected(int s) { for(int i = 1; i <= n; ++i) par[i] = i, het[i] = 1; for(int i = 0; i < m; ++i) { if(s >> i & 1) { int u = find(G[i].u), v = find(G[i].v); if(u == v) continue; par[v] = u; het[u] += het[v]; } } return het[find(1)] == n; } int build(int s) { int sum = 0; cnt = 0; memset(head, -1, sizeof head); for(int i = 0; i < m; ++i) { if(s >> i & 1) { add_edge(G[i].u, G[i].v, G[i].c); add_edge(G[i].v, G[i].u, G[i].c); sum += G[i].c; } } return sum; } int dfn[20], low[20], tim, bcc; bool in[20]; stack<int> s; bool dfs(int u, int f) { dfn[u] = low[u] = ++tim; in[u] = true; s.push(u); for(int i = head[u]; ~i; i = nxt[i]) { int &v = pnt[i]; if(v == f) continue; if(!dfn[v]) { dfs(v, u); low[u] = min(low[u], low[v]); } else if(in[v]) low[u] = min(low[u], dfn[v]); } if(low[u] == dfn[u]) { ++bcc; while(true) { int v = s.top(); s.pop(); in[v] = false; if(v == u) break; } } } bool tarjan() { for(int i = 1; i <= n; ++i) dfn[i] = low[i] = in[i] = 0; tim = bcc = 0; for(int i = 1; i <= n; ++i) { if(!dfn[i]) dfs(i, -1); } return bcc == 1; } int main() { #ifdef LOCAL freopen("in.txt", "r", stdin); // freopen("out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); int kase = 0; while(scanf("%d%d", &n, &m) == 2 && (n || m)) { for(int i = 0; i < m; ++i) scanf("%d%d%d", &G[i].u, &G[i].v, &G[i].c); int ans = INF; for(int i = 0; i < 1 << m; ++i) { if(isConnected(i)) { int cur = build(i); if(cur > ans) continue; if(tarjan()) ans = cur; } } if(ans == INF) printf("There is no reliable net possible for test case %d.\n", ++kase); else printf("The minimal cost for test case %d is %d.\n", ++kase, ans); } return 0; }