首页 > 代码库 > ZOJ2588:Burning Bridges(无向连通图求割边)

ZOJ2588:Burning Bridges(无向连通图求割边)

题目:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588

吐下槽,不得不说ZOJ好坑,模版题做了一个多小时。

题意:
*        给出一个无向图,输入n(表示n个定点,1~n), m(m条边,有重边),
*        (2 <= N <= 10 000, 1 <= M <= 100 000),求这个无向图中的桥,
*        并输出桥属于输入中边的id.

     之前学图的连通性因为没看懂双连通分量,就把连通性的这些知识点搁置了,一直没有刷这方面的题,由于之前已经弄懂求桥的算法,所以看到题就直接上了,结果被一些

小错误给击败了,还好算法的思想没出问题,贴一下代码,以后当模版用。求桥:low[v]>dfn[u](u,v)为树枝边。

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <stack>#define N 10010using namespace std;struct node{    int x,y,w,next,flag;} eg[20*N];int tt,head[N],dfn[N],low[N],ti,n,m,top;int f[20*N];void init(){    tt=0;    ti=1;    top=0;    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(f,false,sizeof(f));}void add(int xx,int yy,int nu){    for(int i=head[xx]; i!=-1; i=eg[i].next)//去重    {        if(eg[i].y==yy)        {            eg[i].flag=1;            return ;        }    }    eg[tt].x=xx;    eg[tt].y=yy;    eg[tt].w=nu;    eg[tt].flag=0;    eg[tt].next=head[xx];    head[xx]=tt++;}void tarjan(int u,int fa){    dfn[u]=low[u]=ti++;    for(int i=head[u]; i!=-1; i=eg[i].next)    {        int v=eg[i].y;        if(v==fa) continue;        if(!dfn[v])        {            tarjan(v,u);            low[u]=min(low[u],low[v]);            if(low[v]>dfn[u]&&!eg[i].flag)            {                f[top++]=eg[i].w;            }        }        else //无向图没有横跨边        {            low[u]=min(dfn[v],low[u]);        }    }}int main(){    int T,xx,yy;    scanf("%d",&T);    while(T--)    {        init();        scanf("%d %d",&n,&m);        for(int i=1; i<=m; i++)        {            scanf("%d %d",&xx,&yy);            add(xx,yy,i);            add(yy,xx,i);        }        tarjan(1,-1);        int sum=0;        for(int i=1; i<=m; i++)        {            if(f[i])                sum++;        }        printf("%d\n",top);        if(top)        {            sort(f,f+top);            for(int i=0; i<top-1; i++)            {                printf("%d ",f[i]);            }            printf("%d\n",f[top-1]);        }        if(T!=0) printf("\n");    }    return 0;}//无向图是没有横边的

我不知道为什么这么写就PE

技术分享
#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>#include <stack>#define N 10010using namespace std;struct node{    int x,y,w,next,flag;}eg[20*N];int tt,head[N],dfn[N],low[N],ti,n,m;bool f[20*N];void init(){    tt=0;    ti=1;    memset(head,-1,sizeof(head));    memset(dfn,0,sizeof(dfn));    memset(f,false,sizeof(f));}void add(int xx,int yy,int nu){    for(int i=head[xx];i!=-1;i=eg[i].next)    {        if(eg[i].y==yy)        {            eg[i].flag=1;            return ;        }    }    eg[tt].x=xx;    eg[tt].y=yy;    eg[tt].w=nu;    eg[tt].flag=0;    eg[tt].next=head[xx];    head[xx]=tt++;}void tarjan(int u,int fa){    dfn[u]=low[u]=ti++;    for(int i=head[u];i!=-1;i=eg[i].next)    {        int v=eg[i].y;        if(v==fa) continue;        if(!dfn[v])        {            tarjan(v,u);            low[u]=min(low[u],low[v]);            if(low[v]>dfn[u]&&!eg[i].flag)            {                f[eg[i].w]=true;            }        }        else //无向图没有横跨边        {            low[u]=min(dfn[v],low[u]);        }    }}int main(){    int T,xx,yy;    scanf("%d",&T);    while(T--)    {        init();        scanf("%d %d",&n,&m);        for(int i=1;i<=m;i++)        {            scanf("%d %d",&xx,&yy);            add(xx,yy,i);            add(yy,xx,i);        }        tarjan(1,-1);        int sum=0;        for(int i=1;i<=m;i++)        {            if(f[i])                sum++;        }        printf("%d\n",sum);        int F=1;        for(int i=1;i<=m;i++)        {            if(f[i])            {                if(F)                {                    printf("%d",i);                    F=0;                }                else printf(" %d",i);            }        }        printf("\n");        if(T!=0) printf("\n");    }    return 0;}//无向图是没有横边的
View Code

 

ZOJ2588:Burning Bridges(无向连通图求割边)