tarjan求割桥
先将图缩点 然后用dfn[u] <= low[v] 求出缩点的数量
对于第一个节点
如果有两个伸出去的根 就说明第一个也是割点
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 1005;
struct Node {
int u;
int v;
int next;
};
Node node[maxn * maxn];
int n, tol, cnt;
int dfn[maxn];
int low[maxn];
bool ans[maxn];
bool vis[maxn];
int fath[maxn];
int head[maxn];
void init() {
cnt = tol = 0;
memset(dfn, 0, sizeof(dfn));
memset(ans, 0, sizeof(ans));
memset(low, 0, sizeof(low));
memset(vis, 0, sizeof(vis));
memset(fath, 0, sizeof(fath));
memset(head, -1, sizeof(head));
}
void addnode(int u, int v){
node[tol].u = u;
node[tol].v = v;
node[tol].next = head[u];
head[u] = tol++;
}
void dfs(int u, int fa){
dfn[u] = low[u] = ++cnt;
fath[u] = fa;
vis[u] = true;
for(int i=head[u]; i!=-1; i=node[i].next) {
int v = node[i].v;
if(!dfn[v]) {
dfs(v, u);
low[u] = min(low[u], low[v]);
} else if(v != fa) {
low[u] = min(low[u], dfn[v]);
}
}
}
void tarjan(){
dfs(1, 0);
}
int solve() {
int root = 0;
int sum = 0;
for(int i=2; i<=n; i++) {
int u = fath[i];
if(u == 1)
root++;
else if(low[i] >= dfn[u]){
ans[u] = true;
}
}
if(root > 1)
sum++;
for(int i=2; i<=n; i++) {
if(ans[i])
sum++;
}
return sum;
}
int main() {
while(scanf("%d", &n), n) {
init();
int u;
while(scanf("%d", &u), u) {
int v;
char ch;
while(1) {
scanf("%d%c", &v, &ch);
addnode(u, v);
addnode(v, u);
if(ch == '\n')
break;
}
}
tarjan();
int ans = solve();
printf("%d\n", ans);
}
return 0;
}