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;
}