码迷,mamicode.com
首页 > 其他好文 > 详细

点双连通分量的求解

时间:2015-06-04 15:27:39      阅读:115      评论:0      收藏:0      [点我收藏+]

标签:

//点双连通分量的求解
//就是通过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

 

点双连通分量的求解

标签:

原文地址:http://www.cnblogs.com/sweat123/p/4551649.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!