这道题要求将无向图按照点-双连通来分块。
#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
*/