POJ3177(3352)(边双连通分量)

题目:

原本没有记录桥是谁,而是染色时即时判断的。后来发现不行,因为a去b可能满足low[b]>dfn[a],但b去a就不满足了。

这是因为low和dfn的关系是相对的,仅限于tarjan时的那棵dfs搜索树中。染色时没有按那棵树走,就不能用dfn和low了!

累加ans时可以把边+=2,很方便。

别忘了写v=edge[i].to。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,r,head[5005],xnt=1,dfn[5005],low[5005],col[5005];
int x,y,tim,cnt,d[5005],ans;
bool b[5005][5005],brg[20005];
struct Edge{
    int next,to,from;
    Edge(int n=0,int t=0,int f=0):next(n),to(t),from(f) {}
}edge[20005];
void dfs(int cur,int fa)
{
//    printf("cur=%d\n",cur);
    dfn[cur]=low[cur]=++tim;
    for(int i=head[cur],v;i;i=edge[i].next)
    {
        if(dfn[v=edge[i].to]&&v!=fa)
            low[cur]=min(low[cur],dfn[v]);
        if(!dfn[v])
        {
            dfs(v,cur);
            low[cur]=min(low[cur],low[v]);
            if(low[v]>dfn[cur])brg[i]=1,brg[i^1]=1;
        }
    }
//    printf("cur=%d dfn=%d low=%d\n",cur,dfn[cur],low[cur]);
}
void cl(int cur,int fa)
{
    col[cur]=cnt;
//    printf("cur=%d col=%d\n",cur,cnt);
    for(int i=head[cur],v;i;i=edge[i].next)
    {
        if(edge[i].to==fa||brg[i])continue;
//        printf("v=%d lowv=%d dfncur=%d\n",edge[i].to,low[edge[i].to],dfn[cur]);
//        if(low[v=edge[i].to]<=dfn[cur]&&!col[v])cl(v,cur);//避免环的死循环 //a去b是桥,b去a就不一定了 
        if(!col[v=edge[i].to])cl(v,cur);//
    }
}
int main()
{
//    freopen("POJ3177.in","r",stdin);
//    freopen("poj3177.out","w",stdout);
//    while(1)
//    {
//        xnt=1;cnt=0;ans=0;tim=0;
//        memset(b,0,sizeof b);
//        memset(col,0,sizeof col);
//        memset(dfn,0,sizeof dfn);
//        memset(low,0,sizeof low);
//        memset(head,0,sizeof head);
//        memset(d,0,sizeof d);
//        memset(brg,0,sizeof brg);
        scanf("%d%d",&n,&r);
        for(int i=1;i<=r;i++)
        {
            scanf("%d%d",&x,&y);
            if(!b[x][y])
            {
                b[x][y]=1;b[y][x]=1;
                edge[++xnt]=Edge(head[x],y,x);head[x]=xnt;
                edge[++xnt]=Edge(head[y],x,y);head[y]=xnt;
            }
        }
        dfs(1,0);
        for(int i=1;i<=n;i++)
            if(!col[i])
            {
                cnt++;cl(i,0);
            }
        for(int i=2;i<=xnt;i+=2)
            if(col[edge[i].from]!=col[edge[i].to])
//            if(brg[i])
            {
                d[col[edge[i].from]]++;d[col[edge[i].to]]++;
//                brg[i]=0;
//                brg[i^1]=0;
            }
        for(int i=1;i<=cnt;i++)
            if(d[i]==1)ans++;
        printf("%d\n",(ans+1)/2);
//    }
    return 0;
}

 

posted on 2018-03-29 12:49  Narh  阅读(139)  评论(0编辑  收藏  举报

导航