无重边无向连通图的割点和桥
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 }