poj 3177

       这是一道求边双连通分量的题目,比较基础,适合刚学过相关算法的人做。题目说的有点花哨,不过基本意思就是如果任意两个点之间至少有两条不同的路径,该添加多少条边。

       至于为什么是用边双连通分量的算法,我也不是很清楚,因为我也是刚接触这种题,所以我只有根据这道题推测一下:边双连通分量简单来说就是一个没有割边的连通分量,所以当找到一条A点到B点的路径是,删除路径的一条边,一定还有另一条路径可以从A点到B点,因为图中无割边,删一条边不会使图不连通。希望各位大神如果发现我的解释有问题,请告诉我一下!

       大体思路:首先求边双连通分量,感觉这个边双连通分量的算法很像求强连通的算法,只不过在更新dfn数组和low数组时有限制,不能用父节点来更新low值。然后将一个边双连通分量缩为一点,并注意转移其相关边的连接关系,当然并不需要真的缩点,具体看代码理解一下。缩点之后的图是一棵树,计算一下叶节点的个数n,那么答案就是(n+1)/2。具体原因可以画图理解一下,按照叶节点是奇数还是偶数分情况讨论一下。此外,根据low值是否相等判断是否属于同一个边双连通分量。

      最后还要补充一下,这道题的图有重边,要去掉重边。(估计是因为这句话“There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path”。而这里的“the same pair of fields”,是指一条边直接连接的两个区域,所以可以直接去除重边,不加考虑)

      参考博文:poj3177-tarjan求桥/割边

      代码(C++):

#include <cstdlib>
#include <iostream>
#include <algorithm>

#define MAXp 5009
#define MAXe (10000*2+9)
using namespace std;

//#define LOCAL

struct Edge{
     int u;
     int v;
     int next;  
} edge[MAXe];

int head[MAXp],dfn[MAXp],low[MAXp],c,ts,odeg[MAXp];
bool map[MAXp][MAXp];

void addEdge(int u,int v)
{
     edge[c].u=u;
     edge[c].v=v;
     edge[c].next=head[u];
     head[u]=c;
     c++;
}

void dfs(int u,int pre)
{
     int i,v;
     dfn[u]=low[u]=++ts;
     for(i=head[u];i!=-1;i=edge[i].next)
     {
         v=edge[i].v;
         if(!dfn[v])
         {
             dfs(v,u);                         
             low[u]=min(low[v],low[u]);      
         }else if(v!=pre) low[u]=min(dfn[v],low[u]);                               
     }
}

int solve(int f)
{
     int i,u,v,ans;
     memset(odeg,0,sizeof(odeg));
     ans=0;
     for(i=0;i<c;i++)
     {
         u=edge[i].u;
         v=edge[i].v;
         if(low[u]!=low[v]) odeg[low[u]]++;       
     }
     for(i=1;i<=f;i++) if(odeg[i]==1) ans++;  

     ans=(ans+1)/2;
     return ans;
}

int main(int argc, char *argv[])
{
#ifdef LOCAL
   freopen("in.txt","r",stdin);
   freopen("out.txt","w",stdout);
#endif
    int r,f,a,b,i;
    while(scanf("%d %d",&f,&r)!=EOF)
    {
        c=0;            
        memset(head,-1,sizeof(head));  
        memset(map,true,sizeof(map));          
        for(i=0;i<r;i++)
        {
            scanf("%d %d",&a,&b);
            if(map[a][b]&&map[b][a])
            {
                addEdge(a,b);
                addEdge(b,a);
                map[a][b]=map[b][a]=false;
            }          
        } 
        ts=0;
        memset(dfn,0,sizeof(dfn));
        dfs(1,-1); 

        printf("%d\n",solve(f));           
    } 
    system("PAUSE");
    return EXIT_SUCCESS;
}

题目(http://poj.org/problem?id=3177):

Redundant Paths
Time Limit: 1000MS Memory Limit: 65536K
   

Description

In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numbered 1..F) to another field, Bessie and the rest of the herd are forced to cross near the Tree of Rotten Apples. The cows are now tired of often being forced to take a particular path and want to build some new paths so that they will always have a choice of at least two separate routes between any pair of fields. They currently have at least one route between each pair of fields and want to have at least two. Of course, they can only travel on Official Paths when they move from one field to another. 

Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way. 

There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.

Input

Line 1: Two space-separated integers: F and R 

Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.

Output

Line 1: A single integer that is the number of new paths that must be built.

Sample Input

7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7

Sample Output

2

Hint

Explanation of the sample: 

One visualization of the paths is: 
   1   2   3
   +---+---+  
       |   |
       |   |
 6 +---+---+ 4
      / 5
     / 
    / 
 7 +
Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions. 
   1   2   3
   +---+---+  
   :   |   |
   :   |   |
 6 +---+---+ 4
      / 5  :
     /     :
    /      :
 7 + - - - - 
Check some of the routes: 
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2 
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4 
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
 
Every pair of fields is, in fact, connected by two routes. 

It's possible that adding some other path will also solve the problem (like one from 6 to 7). Adding two paths, however, is the minimum.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值