poj 1523(无向图求割点)
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 }