POJ 3352 Road Construction【双连通分量_桥】

题意: 一个有 N 个景点的岛,任意两个景点都有道路相连,当道路施工时,游客便不能在该道路上通行,问至少再增加几条道路可以使得在任一条道路维修的情况下,游客都能从岛上任意一个景点到达另一个景点。

分析: 当原图中存在桥的时候,即原图不是双连通图的时候,目的就无法达到,所以这题的关键在于  需要增加几条边可以使得原图中不存在桥。

          可以先找出原图中所有的边双连通分量,对其进行缩点,缩点具体做法是将 图中low值相同的节点看作一个点, 缩点后,原图可以看成是一颗树,而要使得一棵树变为一个双连通图,有一个定理:     增加的边数 = (树中总度数为1的节点数+1)/ 2 

转一大神分析:

对于这种题,我们正常的做法是求桥,删桥,求连通分支,缩点,构建新图,求叶子数。

我们有一种简便方法。需要对tarjan算法做一些变化。我们之前规定low[u]是其子孙通过一条返祖边直接到达的点,把这个改成是其子孙可以连续通过多条返祖边所能到达的点。那么low[u]=min(low[v],dfn[u]);

这样做的缺陷是,不能求割点了,多次返祖会导致求割点的错误,在多环两两以单个点相连排成一条线,且每两个连接点间只有一条边的情况中,那些连接点本应是割点,但是在dfs过程中,这些连接点之间的边又恰好不是树枝边的话,low[u]可能会通过多次返祖,从一个割点不断的经过这些割点到达最上边的割点才记录下low[u]。

这样中间的割点就都不符合dfn(u)<=low[v]了。

但是这样做有一个好处,就是所有的对于边的双连通分支都以low标记出来了,即属于同一双连通分支的所有点的low都等于同一个值。因为在不遇到桥的情况下,low可以返祖到该连同分支在遍历树中的最高点(dfn最小的点)。

这样就相当于整理出了所有的对于边的双连通分支。我们直接遍历所有的边,观察边的两端点是否属于同一分支,若不属于则修改两点的度数。然后看有多少个度数为1的点即可。

 

 

#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
const int maxn=5005;
struct node
{
    int to,next;
}e[10005];
int tot;
int head[maxn];
void add(int s,int u)
{
    e[tot].to=u;
    e[tot].next=head[s];
    head[s]=tot++;
}
int ti,top,sn;
int low[maxn];
void tarjan(int p,int u)
{
    low[u]=++ti;
    int k,i;
    for(i=head[u];i;i=e[i].next)
    {
        k=e[i].to;
        if(k==p)
            continue;
        if(low[k]==0)
            tarjan(u,k);
        if(low[k]<low[u])
            low[u]=low[k];
    }
}
int main()
{
    int n,m,re,i,j,k,a,b;
    int degree[maxn];
    scanf("%d%d",&n,&m);
    ti=0;
    tot=1;
    clr(head);    
    clr(low);
    while(m--)
    {
        scanf("%d%d",&a,&b);
        a--;b--;
        add(a,b);
        add(b,a);
    }
    tarjan(0,0);
    clr(degree);
    for(i=0;i<n;i++)
        for(j=head[i];j;j=e[j].next)
        {
            k=e[j].to;
            if(low[k]!=low[i])
                degree[low[i]]++;
        }
    re=0;
    for(i=1;i<=ti;i++)
        if(degree[i]==1)
            re++;
    printf("%d\n",(re+1)/2);    
    return 0;
}

 

        

 

 

posted @ 2012-07-16 15:00  'wind  阅读(245)  评论(0编辑  收藏  举报