Hiho1186/ 第五十五周 连通性·四 点双连通分量

来源:互联网 发布:积分兑换源码 编辑:程序博客网 时间:2024/05/01 12:12

题意:

给出一幅n个点m条边的连通图 求图中有几个点双连通分量

并输出每条边所在点双连通分量中所有边的编号最小边的编号






代码:

#include<iostream>#include<cstdio>#include<cstring>#define maxn 20050#define maxm 200050using namespace std;struct node{    int id,to,next;}edge[maxm];int head[maxn];int s;int num,dfn[maxn],low[maxn];int sta[maxm],top;int belong[maxm],temp[maxm],block,vis[maxn*5];void Tarjan(int u,int pre){    dfn[u]=low[u]=++num;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(vis[edge[i].id])     //已标记的边不能通过同一条边的反向边再次访问            continue;        if(!dfn[v])        {            sta[top++]=edge[i].id;     //边入栈            Tarjan(v,u);            low[u]=min(low[v],low[u]);            if(dfn[u]<=low[v])            {                block++;                int d=-1,s=0,minn=maxm;                while(d!=edge[i].id)                {                    d=sta[--top];                    temp[s++]=d;                    vis[d]=1;        //标记边                    if(d<minn)                        minn=d;                }                for(int i=0;i<s;i++)                    belong[temp[i]]=minn;            }        }        else if(v!=pre){            sta[top++]=edge[i].id;        //边入栈            low[u]=min(dfn[v],low[u]);        }    }}void init(){    memset(vis,0,sizeof(vis));    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(belong,0,sizeof(belong));    s=top=num=block=0;}int main(){//    freopen("in.txt","r",stdin);    int n,m,a,b;    scanf("%d%d",&n,&m);    init();    for(int i=1;i<=m;i++)    {        scanf("%d%d",&a,&b);        edge[s]={i,b,head[a]};        head[a]=s++;        edge[s]={i,a,head[b]};        head[b]=s++;    }    Tarjan(1,-1);    printf("%d\n",block);    for(int i=1;i<=m;i++)        printf("%d ",belong[i]);    cout<<endl;    return 0;}


0 0
原创粉丝点击