hiho一下 第五十三周(无向图的双连通分量)

这道题要求将无向图按照点-双连通来分块。

#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

*/


你可能感兴趣的:(hiho一下 第五十三周(无向图的双连通分量))