http://poj.org/problem?id=1144
裸的求割点。
u是割点的条件:u是根且有大于一个的儿子,或者u不是根,且u有一个儿子v使得low[v]>=dfn[u]。
code:
#include <stdio.h> #include <string.h> const int maxn = 100 + 5; int edge[maxn][maxn]; int bridge[maxn][maxn], cut[maxn]; int low[maxn], dfn[maxn], vis[maxn]; int root, rt_son; void cut_bridge(int cur, int father, int dep, int n) { //注意:对于每个连通块取一个点x调用cut_bridge(x,-1,0,n),其中n为点数。 vis[cur] = 1; dfn[cur] = low[cur] = dep; for(int i=1; i<=n; ++i) if(edge[cur][i]) { if(i !=father && 1 == vis[i]) { if(dfn[i] < low[cur]) low[cur] = dfn[i]; } if(0 == vis[i]) { cut_bridge(i, cur, dep+1, n); if(cur==root) rt_son++; if(low[i] <low[cur]) low[cur] = low[i]; if((father !=-1&&low[i]>=dfn[cur])) cut[cur] = true; if(low[i]>dfn[cur]) { bridge[cur][i] = bridge[i][cur] = true; } } } vis[cur] = 2; } int main() { int n, i, j, ans; char ch; while(scanf("%d",&n),n) { memset(edge, 0, sizeof edge ); memset(dfn, 0, sizeof dfn ); memset(bridge, 0, sizeof bridge ); memset(cut, 0, sizeof cut ); memset(vis, 0, sizeof vis ); while(scanf("%d",&i),i) { while( (ch=getchar())!='\n' ) { scanf("%d",&j); edge[i][j] = edge[j][i] = 1; } } root = 1, rt_son = 0; cut_bridge(root, -1, 0, n); ans = 0; if(rt_son>1) ans++; for(i=1; i<=n; ++i) if(cut[i]) ans++; printf("%d\n",ans); } return 0; }