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 }
原文地址:https://www.cnblogs.com/Missa/p/3040175.html