poj1523SPF(Tarjan)

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就是割点。

View 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 }

 

 

 

你可能感兴趣的:(tar)