#include <stdio.h> #include <algorithm> #include <the iostream> #include < String .h> the using namespace STD; / * * no request to the cutting point and the bridge of FIG * cutpoint can find and bridges, seek after each point increases deleted block communication. * Note that the processing of heavy edges, the first matrix may be stored, adjacent sub-table, or re-arbitrate * / const int MAXN = 10010 ; const int MAXM = 100010 ; struct Edge { int to, Next; BOOL Cut; // whether the flag bridge } Edge [MAXM]; int head [MAXN], TOT; intLow [MAXN], DFN [MAXN], Stack [MAXN]; int Index, Top; BOOL Instack [MAXN]; BOOL Cut [MAXN]; int add_block [MAXN]; // added after removing a communication point block int Bridge ; void addedge ( int U, int V) { Edge [TOT] .to = V; Edge [TOT] head .next = [U]; Edge [TOT] = .cut to false ; head [U] = TOT ++ ; } void Tarjan ( int U, int pre) { int V; Low [U] = DFN [U] ++ = Index; Stack [Top ++] =U; Instack [U] = to true ; int Son = 0 ; for ( int I = head [U]; I = -! . 1 ; I = Edge [I] .next) { V = Edge [I] .to; IF (V == pre) Continue ; IF (! DFN [V]) { Son ++ ; Tarjan (V, U); IF (Low [U]> Low [V]) Low [U] = Low [V]; // bridge // an undirected edge (u, v) is a bridge, if and only if (u, v) is the side branches, and satisfying the DFS (u) <Low (v ). IF (Low [V]> DFN [u]) { Bridge ++ ; Edge [I] .cut = to true ; Edge [I ^ . 1 ] = .cut to true ; } // cutpoint // a vertex u is cutpoint , satisfied if and only if (1) or (2) (1) u is a root, and u have more than one sub-tree. @ (2) u is not the root, satisfying the presence of (u, v) is a side branch (or parent-child edges, // i.e., u and v father in the search tree), such that the DFS (u) <= Low (V) IF (U! && pre = Low [V]> = DFN [U]) // not a root { Cut [U] = to true ; add_block[u]++; } } else if( Low[u] > DFN[v]) Low[u] = DFN[v]; } //树根,分支数大于1 if(u == pre && son > 1)cut[u] = true; if(u == pre)add_block[u] = son - 1; Instack[u] = false; top--; } void solve(int N) { memset(DFN,0,sizeof(DFN)); memset(Instack,false,sizeof(Instack)); memset(add_block,0,sizeof(add_block)); memset(cut,false,sizeof(cut)); Index = top = 0; bridge = 0; for(int i = 1;i <= N;i++) if(!DFN[i]) Tarjan(i,i); int ans = 0; for(int i = 1;i <= N;i++) if(cut[i]) ans++; printf("%d\n",ans); } void init() { tot = 0; memset(head,-1,sizeof(head)); } int main() { int n; while(scanf("%d",&n), n) { int a,b; char ch; init(); while(scanf("%d",&a),a) { while(scanf("%d%c",&b,&ch)) { addedge(a,b); addedge(b,a); if(ch == '\n') break; } } solve(n); } return 0; }