无重边无向连通图的割点和桥

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<vector>
 4 #include<algorithm>
 5 using namespace std;
 6 vector<vector<int> > g;
 7 int dfn[11000];//节点在dfs过程中的访问序号(也可以叫做开始时间)
 8 int low[11000];//节点的子树中能够通过非父子边追溯到的最早的节点的dfs开始时间
 9 int fa[11000];//dfs树中每个点的父节点
10 int viscv[11000];//标记是否为割点
11 int ntime;//dfs中记录时间
12 int n,m;//点数和边数
13 void tarjan(int u,int father)//father是u的父节点
14 {
15     fa[u]=father;
16     int i;
17     low[u]=dfn[u]=ntime++;
18     for(i=0;i<g[u].size();i++)
19     {
20         int v=g[u][i];
21         if(!dfn[v])
22         {
23             tarjan(v,u);
24             low[u]=min(low[u],low[v]);
25         }
26         else if(father!=v)
27         {
28             low[u]=min(low[u],dfn[v]);
29         }
30     }
31 }
32 void solve()
33 {
34     int sontree=0;//dfs树中根节点的子树的数目
35     int i;
36     tarjan(1,0);
37     for(i=2;i<=n;i++)
38     {
39         int v=fa[i];
40         if(v==1) sontree++;
41         else
42         {
43             if(dfn[v]<=low[i])
44                 viscv[v]=1;
45         }
46     }
47     if(sontree>1) viscv[1]=1;
48     for(i=1;i<=n;i++)
49     {
50         if(viscv[i])
51             printf("%d\n",i);
52     }
53     for(i=1;i<=n;i++)
54     {
55         int v=fa[i];
56         if(v>0&&dfn[v]<low[i])
57             printf("%d %d\n",v,i);
58     }
59 }
60 int main()
61 {
62     int u,v,i;
63     ntime=1;
64     while(scanf("%d%d",&n,&m)!=EOF)
65     {
66     g.clear();
67     g.resize(11000);
68     ntime=1;
69     for(i=0;i<m;i++)//点编号是从1开始的
70     {
71         scanf("%d%d",&u,&v);
72         g[u].push_back(v);
73         g[v].push_back(u);
74     }
75     memset(dfn,0,sizeof(dfn));
76     memset(low,0,sizeof(low));
77     memset(fa,0,sizeof(fa));
78     memset(viscv,0,sizeof(viscv));
79     solve();
80     }
81     return 0;
82 }

 

posted @ 2016-05-04 21:08  2014551532  阅读(137)  评论(0编辑  收藏  举报