http://poj.org/problem?id=1523
参考着各种书籍 网上的讲解 及各种tarjan算法 总算 把它捣鼓出来了
这题是求割点 及割点分割出来的块数 模板题 块数利用dfs可加出来
http://blog.csdn.net/lyy289065406/article/details/6752662从这偷来一些知识点
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就是割点。
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 }