pku 3177Redundant Paths(需要判断重边后再构造边双连通分量)

比pku 3352 Road Construction烦一些,就是要判断重边而已

#include <stdio.h>
#include <string.h>

 

#define MAXN 5001
#define MAXM 10001*2

 

//并查集
int father[MAXN];
int find_mfs(int x)
{
    int i;
    for(i=x; father[i]>0; i=father[i]) ;
    //路径压缩
    while(x!=i)
    {
        int t=father[x];
        father[x]=i;
        x=t;
    }
    return i;
}
void merge_mfs(int x,int y)
{
    int fx,fy;
    fx=find_mfs(x);
    fy=find_mfs(y);
    if(fx==fy) return;
    if(father[fx]>father[fy])//例如-3>-4,但绝对值3<4
    {
        father[fy]+=father[fx];
        father[fx]=fy;
    }
    else
    {
        father[fx]+=father[fy];
        father[fy]=fx;
    }
}

struct edge
{
    int adv,next;
};
edge p[MAXM];
int index;

int adjlist[MAXN];
int N,M,times,dfn[MAXN],low[MAXN],degree[MAXN];

inline void insert(int i,int j)
{
    /*方法1,在建图时判重 0MS*/
    for(int ii=adjlist[i]; ii != -1; ii=p[ii].next)
    {
        int jj=p[ii].adv;
        if(jj==j) return;
    }
    p[index].adv=j;
    p[index].next=adjlist[i];
    adjlist[i]=index++;
}

inline int Min(int a,int b)
{
    return a<b?a:b;
}

void dfs(int u,int ufa)
{
    dfn[u]=low[u]=++times;
    for(int j=adjlist[u]; j != -1; j=p[j].next)
    {
        int v=p[j].adv;
        if( !dfn[v] )
        {
            dfs(v,u);
            low[u]=Min(low[u],low[v]);
            if( ! (dfn[u] < low[v]) )//(u,v)不是桥
            {
                //则u、v属于同一个边双连通分量
                merge_mfs(u,v);
            }
          /*
          //  方法2,在这里搞。32MS
            else
            {
                int jj,vv;
                for(jj=adjlist[u]; jj != -1; jj=p[jj].next)
                {
                    vv=p[jj].adv;
                    if(vv==v && jj != j) break;
                }
                if(jj!=-1)
                    merge_mfs(u,v);
            }*/
        }
        else if(v!=ufa)
        {
            low[u]=Min(low[u],dfn[v]);
        }
    }
}

void shrink(int &bcn)
{
    int i,j,ifather,jfather;
    for(i=1; i<=N; i++)
    {
        ifather=find_mfs(i);
        for(j=adjlist[i]; j != -1; j=p[j].next)
        {
            jfather=find_mfs(p[j].adv);
            if(ifather != jfather)
            {
                degree[jfather]++;
                if(jfather>bcn) bcn=jfather;
            }
        }
    }
}

int main()
{
    int i,j;
    while(scanf("%d%d",&N,&M)!=EOF)
    {
        index=0;
        memset(adjlist,-1,sizeof(adjlist));
        while(M--)
        {
            scanf("%d %d",&i,&j);
            insert(i,j);
            insert(j,i);
        }
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        times=0;
        memset(father,-1,sizeof(father));
        dfs(1,-1);
        memset(degree,0,sizeof(degree));
        int bcnt=-1;
        shrink(bcnt);
        for(i=1,j=0; i<=bcnt; i++)
        {
            if(degree[ i ] == 1) j++;
        }
        printf("%d\n",(j+1)/2);
    }
    return 0;
}

 

posted @ 2010-08-18 19:26  菜到不得鸟  阅读(318)  评论(1)    收藏  举报