点双连通分量的求解

//点双连通分量的求解
//就是通过tarjan算法求出关节点时,与关节点的子树就是一个连通分量,可以通过画图得到
//所以可以将与顶点u有关的边放到栈中,然后一但满足low[v]>=dfn[u](表面点u是割点)(注释:由于dfs,已经建好了u
//的子树,所以栈中有顶点u的子树),就可以进行退栈,直到遇到与u相关的边(由于dfs原因,之前的边都已经存入栈中
//所以第一个(u,v)边是最后一个退栈的,所以到其为止即可。)由于让访问过的边map[u][v]=map[v][u]=2,所以之前访问
//过的边不会再被访问。在dfs生成树图中能够很明显看出,就是关节点未被访问过的子树。

 1 #include<stdio.h>

 2 #include<string.h>

 3 #include<stack>

 4 using namespace std;

 5 int min(int x,int y)

 6 {

 7     return x<y?x:y;

 8 }

 9 

10 int map[100][100],vis[100],dfn[100],depth,low[100],n,m;

11 void init()

12 {

13     int i,j;

14     memset(vis,0,sizeof(vis));

15     vis[1]=1;

16     low[1]=dfn[1]=1;

17     depth=1;

18 }

19 struct edge

20 {

21     int x;

22     int y;

23 };

24 stack<edge>s;

25 void dfs(int u)

26 {

27     int i,j;

28     for(i=1;i<=n;i++)

29     {

30         if(map[u][i]==1)

31         {

32             map[u][i]=map[i][u]=2;//标记为2使该边使用后不再被使用

33             edge t={u,i};

34             s.push(t);

35             if(!vis[i])

36             {

37                 vis[i]=1;

38                 depth++;

39                 dfn[i]=low[i]=depth;

40                 dfs(i);

41                 low[u]=min(low[u],low[i]);

42                 if(low[i]>=dfn[u])

43                 {

44                     while(1)//不断退栈,直到遇到边(u,v)

45                     {

46                         edge temp;

47                         temp=s.top();

48                         s.pop();

49                         printf("%d-%d ",temp.x,temp.y);

50                         if((temp.x==u&&temp.y==i)||(temp.x==i&&temp.y==u))

51                         {

52                             break;

53                         }

54                     }

55                     printf("\n");

56                 }

57             }

58             else low[u]=min(low[u],dfn[i]);

59         }

60     }

61 }

62 int main()

63 {

64     int i,j,v,u;

65     while(scanf("%d%d",&n,&m)!=EOF)

66     {

67         memset(map,0,sizeof(map));

68         for(i=0;i<m;i++)

69         {

70             scanf("%d%d",&u,&v);

71             map[u][v]=map[v][u]=1;

72         }

73         init();

74         dfs(1);

75     }

76 }

77 /*

78 7 9

79 1 2

80 1 3

81 1 6

82 1 7

83 2 3

84 2 4

85 2 5

86 4 5

87 6 7

88 */
View Code

 

你可能感兴趣的:(点双连通分量的求解)