这道题要求将无向图按照点-双连通来分块。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int INF=1<<29; const int maxn=20001; const int maxm=100012*2; int e=0,pnt[maxm],nxt[maxm],head[maxm]; int low[maxn],vis[maxn],dfn[maxn],belong[maxn],st[maxn]; int n,m,depth,cnt,top; int num[maxn]; void init() { e=0; memset(head,-1,sizeof(head)); top=depth=cnt=0; memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++)num[i]=INF; } void AddEdge(int u,int v) { pnt[e]=v; nxt[e]=head[u]; head[u]=e++; } void dfs(int now,int father) { //printf("%d %d\n",now,father); low[now]=dfn[now]=++depth; vis[now]=1; st[top++]=now; for(int i=head[now]; i!=-1; i=nxt[i]) { if(!dfn[pnt[i]]) { dfs(pnt[i],now); low[now]=min(low[now],low[pnt[i]]); } else if(pnt[i]!=father) low[now]=min(low[now],dfn[pnt[i]]); } if(low[now]==dfn[now]) { cnt++; int j; while(j=st[--top]) { belong[st[top]]=cnt; if(j==now) break; } } } int main() { scanf("%d%d",&n,&m); init(); for(int i=0; i<m; i++) { int u,v; scanf("%d%d",&u,&v); AddEdge(u,v); AddEdge(v,u); } dfs(1,-1); // for(int i=1;i<=n;i++) // printf("%d ",belong[i]);puts(""); // for(int i=1;i<=n;i++) // printf("%d ",belong[i]);puts(""); for(int i=1;i<=n;i++) { int t=belong[i]; num[t]=min(num[t],i); } printf("%d\n",cnt); for(int i=1;i<=n;i++) printf("%d%c",num[belong[i]],i==n?'\n':' '); return 0; } /* 6 7 1 4 4 5 5 1 4 2 2 3 3 6 6 2 */