​http://poj.org/problem?id=1523​

参考着各种书籍 网上的讲解 及各种tarjan算法 总算 把它捣鼓出来了

这题是求割点  及割点分割出来的块数 模板题 块数利用dfs可加出来

从这偷来一些知识点

1、【割点】

在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为割点集合。当割点集合的顶点个数只有1个时,该顶点就是割点。

 

2、【连通分量】

当删除某个割点后,原图会被划分为若干个互不连通的子图,这些子图就是该割点对应的连通分量。

  此时,我们可以得到割点的定义如下:

若有k的儿子为i,我们定义AnceDeep[i]为结点i辈分最高(深度最浅)的祖先的深度,deep[k]为k的搜索深度(时间戳),那么k为割点当且仅当k满足(1)(2)中的一个:

(1)       若k为深搜树的根Root,当且仅当k的儿子数(分支数)>=2时k为割点;

(2)       若k为搜索树的中间结点(即k既不为根也不为叶),那么k必然有father和son,若AnceDeep[son]>= deep[k],则k必然为割点。

 

对于(1)是显然的,根结点k一旦有2个以上的分支,那么删除k必然出现森林;

对于(2)比较难理解,首先注意AnceDeep[son]>= deep[k]这个条件,意思就是“k的儿子son的辈分最高的祖先(暂且设其为w)的深度,比k的深度要深(或者等于k的深度,此时k就是w),就是说k的辈分比w更高(深度更浅),那么一旦删除k,son所在的网络势必和 k的father所在的网络断开”,那么k就是割点。


poj1523SPF(Tarjan)_i++poj1523SPF(Tarjan)_子图_02View Code


1 #include <iostream>
2 #include<cstdio>
3 #include<cstring>
4 #include<stdlib.h>
5 #include<algorithm>
6 using namespace std;
7 struct node
8 {
9 int u,v,next;
10 }edge[10100];
11 int t,first[2010],dfn[1010],low[1010],sum[1010],dc,stack[1010],top;
12 void init()
13 {
14 t = 0;
15 memset(first,-1,sizeof(first));
16 }
17 void add(int u,int v)
18 {
19 edge[t].u = u;
20 edge[t].v = v;
21 edge[t].next = first[u];
22 first[u] = t++;
23 }
24 void dfs(int u,int fa)
25 {
26 int i,j;
27 low[u] = dfn[u] = ++dc;
28 int child = 0;
29 for(i = first[u] ; i != -1 ;i = edge[i].next)
30 {
31 int v = edge[i].v;
32 if(!dfn[v])
33 {
34 child++;
35 dfs(v,u);
36 low[u] = min(low[u],low[v]);
37 if(low[u]>=dfn[u])sum[u]++;
38 }
39 else
40 {
41 if(v!=fa)
42 low[u] = min(low[u],dfn[v]);
43 }
44 }
45 if(fa==0)//这为上述判断割点的两种情况
46 {
47 if(child>1)
48 {
49 sum[u] = child;
50 stack[top++]= u;
51 }
52 }
53 else
54 {
55 if(sum[u]>=1)
56 {
57 stack[top++] = u;
58 sum[u]++;
59 }
60 }
61 }
62 int main()
63 {
64 int i,j,k,n,m,a,b,kk=0;
65 while(cin>>a)
66 {
67 if(a==0)break;
68 kk++;
69 top=0;
70 init();
71 memset(dfn,0,sizeof(dfn));
72 memset(low,0,sizeof(low));
73 memset(sum,0,sizeof(sum));
74 cin>>b;
75 add(a,b);add(b,a);
76 while(cin>>a)
77 {
78 if(a==0)break;
79 cin>>b;
80 add(a,b);add(b,a);
81 }
82 n = 1000;
83 dc=0;
84 for(i = 1 ; i <= n ; i++)
85 {
86 if(dfn[i]==0)
87 dfs(i,0);
88 }
89 sort(stack,stack+top);
90 printf("Network #%d\n",kk);
91 for(i = 0 ; i < top ; i++)
92 printf(" SPF node %d leaves %d subnets\n",stack[i],sum[stack[i]]);
93 if(top==0)
94 puts(" No SPF nodes");
95 puts("");
96 }
97 return 0;
98 }