一些直白的理解,和标准定义有差别,但也足够了
点双连通:一个图任意去掉一个点后仍然联通( 或者说任意两点件都有两条路径(无任何重叠的边) ) ; 边双连通同理
割点:去掉某个点后,图不连通 割边同理
求割点 ( low[y]>=dfn[x] )
#include <bits/stdc++.h> using namespace std ; const int N=2*1e4+3,M=5*1e5+2; int dfn[N],low[N],n,m,pool; int ans,cut[N]; int all,go[M],nxt[M],hd[N]; void add(int x,int y){ all++; go[all]=y,nxt[all]=hd[x],hd[x]=all; } void tar(int x,int fa){ dfn[x]=low[x]=++pool; int y,c=0; for(int i=hd[x];i;i=nxt[i]){ y=go[i]; if(!dfn[y]){ c++,tar(y,x),low[x]=min(low[x],low[y]); if(fa==0&&c>1||fa&&dfn[x]<=low[y]) ans+=(cut[x]?0:1),cut[x]=1; } else if(y!=fa) low[x]=min(low[x],dfn[y]); } } int main(){ int i,x,y; cin>>n>>m; for(i=1;i<=m;i++) cin>>x>>y,add(x,y),add(y,x); for(i=1;i<=n;i++) if(!dfn[i]) tar(i,0); cout<<ans<<'\n'; for(i=1;i<=n;i++) if(cut[i]) cout<<i<<' '; }
求割边
#include<bits/stdc++.h> using namespace std ; const int N=3*1e4+2,M=4*N; int ans,nxt[M],go[M],hd[N],all; void add(int x,int y){ go[++all]=y,nxt[all]=hd[x],hd[x]=all; } int dfn[N],low[N],n,m,pool; void tarjan(int x,int fa){ dfn[x]=low[x]=++pool; int i,y; for(i=hd[x];i;i=nxt[i]){ y=go[i]; if(!dfn[y]){ tarjan(y,x),low[x]=min(low[x],low[y]); if(dfn[x]<low[y]) ans++; //bridge[i]=bridge[i^1]=1 } else if(y!=fa) low[x]=min(low[x],dfn[y]); } } void init(){ for(int i=1;i<=n;i++) hd[i]=dfn[i]=0; all=1; ans=pool=0; } int main(){ int i,x,y; while(cin>>n>>m,n){ init(); for(i=1;i<=m;i++) cin>>x>>y,add(y,x),add(x,y); for(i=1;i<=n;i++) if(!dfn[i]) tarjan(i,0); cout<<ans<<endl; } }