题目链接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122091#problem/B
题意: :有n个电话,有一些线连接在他们之间,有的电话如果不能工作了,则可能导致n个电话不连通了,求出这样的电话又几个,其实就是求割点有多少个
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #include<cstring> #include<vector> using namespace std; #define maxn 10005 vector<vector<int> > G; int father[maxn], low[maxn], dfn[maxn], cut[maxn]; int times, n; void Init() { G.clear(); G.resize(n+5); memset(father, 0, sizeof(father)); memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); memset(cut, 0, sizeof(cut)); times = 0; } void Tarjan(int u, int fa) { low[u] = dfn[u] = ++times; father[u] = fa; int len = G[u].size(),v; for(int i=0; i<len; i++) { v = G[u][i]; if(!dfn[v]) { Tarjan(v, u); low[u] = min(low[u], low[v]); } else if(fa != v) low[u] = min(low[u], dfn[v]); } } int solve() { int bs=0, ans=0, v; Tarjan(1, 0); for(int i=2; i<=n; i++) { v = father[i]; if(v == 1) bs ++; else if(dfn[v] <= low[i]) cut[v] = 1; } for(int i=2; i<=n; i++) { if(cut[i]) ans++; } if(bs > 1) ans++; return ans; } int main() { while(scanf("%d", &n),n) { int a, b; char ch; Init(); while(scanf("%d", &a), a) { while(scanf("%d%c",&b, &ch)) { G[a].push_back(b); G[b].push_back(a); if(ch == '\n') break; } } printf("%d\n", solve()); } return 0; }