POJ1144Network(求割点个数)

题目链接

题意:一共n割点,然后若干行,每行第一个输入一个点,然后若干个点表示与他相连,0单独一行表示一个样例的结束。然后求图中的割点个数

割点:去掉该点之后得到的图不在连通,那么该店就是割点

一般割点有两种情况:1、父节点,当有两个或两个以上儿子节点的时候 2、dfn[x]表示深搜是x点是第几个开始搜索的,low[x]表示x及其父节点所能指向的最早的祖先,这个边官方就做回边,也就是回边往上能最高能到哪。如果 low[x] >= dfn[x] 也就是说x他的儿子们最多到x甚至还在x的下面,所以x就是割点,去掉x时候,x的儿子们就和x的上面的祖先们失去了联系

然后就是对low[u]的更新:普通情况下,就是u->v,然后v没有没访问,所以low[u] = min( low[u], low[v]) 另一中情况就是回边的情况,u->v然而v已经访问完了,说明v在上面,u是下面的,u是指向祖先的。此时 low[u] = min( low[u], dfn[v]);

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 using namespace std;
 7 const int Max = 105;
 8 vector<int> g[Max];
 9 int vis[Max],low[Max],pre[Max],iscut[Max];
10 int n,root,time;
11 int get_min(int x, int y)
12 {
13     if(x > y)
14         return y;
15     return x;
16 }
17 void dfs(int u)
18 {
19     int child = 0;
20     pre[u] = low[u] = ++time;
21     vis[u] = 1;
22     int len = g[u].size();
23     for(int i = 0; i < len; i++)
24     {
25         int w = g[u][i];
26         if(!vis[w])
27         {
28             child++;
29             dfs(w);
30             low[u] = get_min(low[u], low[w]);
31             if(u == root && child == 2)  //根节点如果有两个以上儿子节点就是割点
32                 iscut[u] = 1;
33             if(u != root && low[w] >= pre[u]) //u的子孙节点如果指向的最早节点还比u要大的话,u也是割点
34                 iscut[u] = 1;
35         }
36         else if(w != u)  // 这是应该避免重点的情况吗?
37             low[u] = get_min(low[u], pre[w]);
38     }
39 }
40 int main()
41 {
42     while (scanf("%d", &n) != EOF && n)
43     {
44         int a, b;
45         for(int i = 0; i <= n; i++)
46             g[i].clear();
47         while(scanf("%d", &a) && a)
48         {
49             char ch;
50             while ( (ch = getchar()) != '\n')
51             {
52                 scanf("%d", &b);
53                 g[a].push_back(b);
54                 g[b].push_back(a);
55             }
56         }
57         memset(pre, 0, sizeof(pre));
58         memset(vis, 0, sizeof(vis));
59         memset(low, 0, sizeof(low));
60         memset(iscut, 0, sizeof(iscut));
61         time = 0;
62         root = 1;
63         dfs(1);
64         int ans = 0;
65         for(int i = 1; i <= n; i++)
66             if(iscut[i])
67                 ans++;
68         printf("%d\n", ans);
69     }
70 }
View Code

 

posted @ 2016-03-15 15:34  zhaop  阅读(165)  评论(0编辑  收藏  举报