1 /*
2 构建一棵dfs树,序列dfn[i]为深度优先数,表示dfs时访问i节点的序号,low[i]表示从i节点出发能访问到的最小的深度优先数。
3
4 当且仅当节点u满足如下两个条件之一时,u为割点:
5 1.u为dfs树的根,且u至少有两个子节点。
6 2.u不是dfs树的根,至少存在一个节点v是u的子节点,且low[v]>=dfn[u]。
7
8 若u为割点,记subnets[u]为u的子节点数,则去掉u后,图被分成subnets[u]+1个部分(每个子节点的部分和u的祖先的部分),若u为dfs树的根,则分成subnets[u]个部分(根节点没有祖先)。
9 */
10 // File Name: 1523.cpp
11 // Author: Missa
12 // Created Time: 2013/4/24 星期三 13:53:18
13 //O(n^2)
14 #include<iostream>
15 #include<cstdio>
16 #include<cstring>
17 #include<algorithm>
18 #include<cmath>
19 #include<queue>
20 #include<stack>
21 #include<string>
22 #include<vector>
23 #include<cstdlib>
24 #include<map>
25 #include<set>
26 using namespace std;
27 #define CL(x,v) memset(x,v,sizeof(x));
28 #define R(i,st,en) for(int i=st;i<en;++i)
29 #define LL long long
30
31 const int inf = 0x3f3f3f3f;
32 const int maxn = 1e3+5;
33 vector <int> adj[maxn];
34 bool vis[maxn];
35 int n, tmpdfn, son, dfn[maxn], low[maxn], subnets[maxn];//顶点,当前dfn,儿子数,dfn,low,去掉此节点被分成的部分数
36 void dfs(int u)
37 {
38 int size = adj[u].size();
39 for (int i = 0; i < size; ++i)
40 {
41 int v = adj[u][i];
42 if (!vis[v])
43 {
44 vis[v] = 1;
45 tmpdfn ++;
46 dfn[v] = low[v] = tmpdfn;
47 dfs(v);
48 low[u] = min(low[u], low[v]);
49 if (low[v] >= dfn[u])
50 {
51 if (u != 1) subnets[u] ++;//u的子节点数
52 //根结点的子女结点的个数(如果大于1,则根结点是关节点)
53 if (u == 1) son++;
54 }
55 }
56 else low[u] = min(low[u], dfn[v]);
57 }
58 }
59 void init()
60 {
61 low[1] = dfn[1] = 1;
62 tmpdfn = 1;
63 son = 0;
64 memset(vis, 0, sizeof(vis));
65 vis[1] = 1;
66 memset(subnets, 0, sizeof(subnets));
67 }
68
69 int main()
70 {
71 int u, v, flag, cas = 1;
72 while(~scanf("%d",&u))
73 {
74 if (!u) break;
75 init();
76 memset(adj, 0, sizeof(adj));
77 n = 0;
78 scanf("%d", &v);
79 adj[u].push_back(v);
80 adj[v].push_back(u);
81 n = max(u,v);
82 while (~scanf("%d", &u))
83 {
84 if (!u) break;
85 scanf("%d",&v);
86 n = max(n, max(u,v));
87 adj[u].push_back(v);
88 adj[v].push_back(u);
89 }
90 if (cas != 1) printf("\n");
91 printf("Network #%d\n", cas++);
92 dfs(1);
93 if (son > 1) subnets[1] = son - 1;
94 bool ok = 0;
95 for (int i = 1; i <= n; ++i)
96 {
97 if (subnets[i])
98 {
99 ok = 1;
100 printf(" SPF node %d leaves %d subnets\n",i, subnets[i] + 1);//u的子节点数+u的祖先
101 }
102 }
103 if (!ok) printf(" No SPF nodes\n");
104 }
105 return 0;
106 }