#1184 : 连通性二·边的双连通分量
贴板子。求割边。将>改为>=即可判断u是否为割点。
#include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int INF=0x3f3f3f3f; const int maxn=20008; const int maxm=100008; struct fuck{ int u,v,next; bool ban; }edge[maxm<<1]; int tol; int head[maxn]; void init() { tol=0; memset(head,-1,sizeof(head)); } void addedge(int u,int v) { edge[tol].u=u; edge[tol].v=v; edge[tol].next=head[u]; edge[tol].ban=false; head[u]=tol++; } int tim=0; int pre[maxn],low[maxn]; int tarj(int u,int fa) { int lowu=pre[u]=++tim; int child=0; int i,v,lowv; for(i=head[u];i!=-1;i=edge[i].next) { v=edge[i].v; if(!pre[v]) { child++; lowv=tarj(v,u); lowu=min(lowu,lowv); if(lowv>pre[u]) { edge[i].ban=true; edge[i^1].ban=true; } } else if(pre[v]<pre[u]&&v!=fa) lowu=min(lowu,pre[v]); } low[u]=lowu; return lowu; } int uni[maxn]; bool vis[maxn]; void dfs(int u,int idx) { int i,v; vis[u]=true; uni[u]=idx; for(i=head[u];i!=-1;i=edge[i].next) { if(edge[i].ban||vis[edge[i].v]) continue; v=edge[i].v; dfs(v,idx); } } int main() { int i,j,n,m,u,v; while(scanf("%d%d",&n,&m)==2) { init(); for(i=1;i<=m;i++) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } tim=0; memset(pre,0,sizeof(pre)); tarj(1,-1); memset(vis,false,sizeof(vis)); int ans=0; for(i=1;i<=n;i++) if(!vis[i]) { dfs(i,i); ans++; } printf("%d\n",ans); for(i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%d",uni[i]); } printf("\n"); } return 0; }