1 条题解
-
1dsl2002 LV 8 @ 2017-05-25 22:53:47
对于每一个点双联通分量,如果它与两个及以上割点相连,则不需要修建逃生出口,因为其一定可以通过其他割点走到其他逃生出口。如果它只与一个割点相连,则一定需要修建一个逃生出口。
#include <cstring> #include <cstdio> #include <cstdlib> using namespace std; const int maxn = 505; struct edge { int to, next; }e[maxn * 2]; int m, n, h[maxn], tot; int dfn[maxn], low[maxn], Time; int vis[maxn]; bool iscut[maxn]; long long ans1, ans2; inline void add(int u, int v) { e[++tot] = (edge) {v, h[u]}; h[u] = tot; } inline void chkmax(int &a, int b) { if(a < b) a = b; } inline void chkmin(int &a, int b) { if(a > b) a = b; } int root; void tarjan(int u, int fa) { dfn[u] = low[u] = ++Time; vis[u] = 1; int child = 0; for(int i = h[u]; i; i = e[i].next) { int v = e[i].to; if(v == fa) continue; if(!dfn[v]) { child++; tarjan(v, u); chkmin(low[u], low[v]); if(u == root && child >= 2) iscut[u] = true; else if(u != root && dfn[u] <= low[v]) iscut[u] = true; }else if(vis[v] == 1) chkmin(low[u], dfn[v]); } if(u == fa && child == 1) iscut[u] = false; vis[u] = 2; } int size, sum, now; void dfs(int u) { vis[u] = now; size++; for(int i = h[u]; i; i = e[i].next) if(!vis[e[i].to] && !iscut[e[i].to]) dfs(e[i].to); else if(vis[e[i].to] != now && iscut[e[i].to]) vis[e[i].to] = now, sum++; } int main() { int i, u, v, Case = 0; while(scanf("%d", &m) == 1 && m) { memset(h, 0, sizeof(h)); memset(dfn, 0, sizeof(dfn)); memset(vis, 0, sizeof(vis)); memset(iscut, 0, sizeof(iscut)); tot = n = Time = 0; for(i = 1; i <= m; i++) { scanf("%d%d", &u, &v); add(u, v); add(v, u); chkmax(n, u); chkmax(n, v); } for(i = 1; i <= n; i++) if(!dfn[i]) root = i, tarjan(i, i); ans1 = 0; ans2 = 1; memset(vis, 0, sizeof(vis)); for(i = 1; i <= n; i++) if(!vis[i] && !iscut[i]) { now++; size = sum = 0; dfs(i); if(sum == 1) ans1++, ans2 *= size; } if(ans1 == 0) ans1 = 2, ans2 = n * (n - 1) / 2; printf("Case %d: %lld %lld\n", ++Case, ans1, ans2); } return 0; }
ps:如果这道题为非连通图则我的代码还有错误,但并没有这样的数据,所以我开开心心的AC啦
- 1
信息
- 难度
- 9
- 分类
- (无)
- 标签
- 递交数
- 8
- 已通过
- 4
- 通过率
- 50%
- 被复制
- 1
- 上传者