题意:给一个无向图,问需要补多少条边才可以让整个图变成【边双连通图】,即任意两个点对之间的一条路径全垮掉,这两个点对仍可以通过其他路径而互通。

思路:POJ 3352的升级版,听说这个图会给重边。先看3352的题解http://www.cnblogs.com/xcw0754/p/4619594.html。

  其实与3352不同的就是重边出现了怎么办?假如出现的重边刚好是桥呢?

  首先要知道,【割点】可以将两个【点双连通分量】隔开来,因为仅一个【点双连通分量】中肯定无割点,那么每两个点对都同时处于若干个简单环中才能当一个点撤掉仍然可以互通。

  而【桥】可以将两个【边双连通分量】隔开来,因为仅仅一个【边双连通分量】中肯定无桥,那么每两个点对之间肯定有多条路径可达(边都是不同的),当任意1条边撤掉后每两个点对仍然可达。

  以上两点很重要,根据第二点,我们知道,如果在一个【边双连通分量】中任意两个有边相连的点再添加任意条边都是不影响的,任意两点间依然有多条不同的【边】路径可达。但是如果桥出现了重边呢?那么该桥上的两点会同时属于一个【边双连通分量】,此时就会将两个【边双连通分量】合并为一。

  如何判别桥是否出现重边?我们一般以t!=far来判别是否遇到一条边通往父亲,但是现在要变了,我们要判断是否遇到这条边多次,如果多次,要更新本节点x的low值了,应该用low[x]=min(low[x],dfn[far])来更新,更新完之后他们的low值自然会处于同一个领导之下,此时再按照3352中用的类似于并查集的方法就可以将其彻底归到同一个【边双连通分量】中。

特别注意:求点双连通分量时要注意在t!=far前加上这个条件“ dfn[t]<dfn[x] ”。如果不求这个可以不加,因为t如果已经遍历过,且dfn[t]>dfn[x],那么肯定在x之上访问过,此时dfn[t]可能可以更新到low[x],但是如果dfn[t]<dfn[x],且在x之下访问过,那么dfn[t]肯定比dfn[x]还小,那肯定比low[x]小,则更新不到,也不产生影响,所以也不用去判断dfn[t]<dfn[x]。

 #include <iostream>
#include <cmath>
#include <cstdio>
#include <vector>
#include <cstring>
#include <set>
using namespace std;
const int N=+;
vector<int> vect[N];
int low[N], dfn[N], pre[N], cnter;
int du[N];
vector<pair<int,int> > cutt;
int find(int x) //寻找x的low值
{
if(low[x]==dfn[x]) return low[x];
return low[x]=find( pre[low[x] ] );
} void DFS(int x, int far)
{
low[x]= dfn[x]= ++cnter;
pre[cnter]=x; //第cnter个访问的是x
int times=; //记录桥是否有两条,若有,则要更新low值
for(int i=; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(!dfn[t])
{
DFS(t,x);
low[x]=min(low[x],low[t]);
if(low[t]>dfn[x]) cutt.push_back(make_pair(x,t));
}
else if(t!=far) low[x]=min(low[x],dfn[t]);
else
{
if(times>) //重边,low应该更新为far才对。
low[x]=min(low[x],dfn[far]);
times++;
}
}
} int cal_bcc(int f) //找桥
{
cutt.clear();
memset(du,,sizeof(du));
memset(low,,sizeof(low));
memset(dfn,,sizeof(dfn));
memset(pre,,sizeof(pre));
cnter=;
DFS(,); for(int i=; i<cutt.size(); i++)
{
int a=cutt[i].first;
int b=cutt[i].second;
du[find(a)]++;
du[find(b)]++;
}
int ans=;
for(int i=; i<=f; i++)
if(du[i]==) ans++;
/*
如果叶子数为偶数,可以采用互缠。
比如叶子顺序1234可以1-3,2-4。
注意奇数个叶子的情况。
*/
return ((ans+)/);
} int main()
{
freopen("input.txt", "r", stdin);
int f, r, a, b, j=;
char s[N];
while(cin>>f>>r)
{
for(int i=; i<=f; i++) vect[i].clear();
while(r--)
{
scanf("%d%d", &a, &b);
vect[a].push_back(b);
vect[b].push_back(a);
}
printf("%d\n",cal_bcc(f));
}
return ;
}

AC代码

POJ 3177 Redundant Paths (桥,边双连通分量,有重边)的更多相关文章

  1. POJ 3177 Redundant Paths(边双连通分量)

    [题目链接] http://poj.org/problem?id=3177 [题目大意] 给出一张图,问增加几条边,使得整张图构成双连通分量 [题解] 首先我们对图进行双连通分量缩点, 那么问题就转化 ...

  2. POJ 3177 Redundant Paths(边双连通的构造)

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13717   Accepted: 5824 ...

  3. POJ - 3177 Redundant Paths (边双连通缩点)

    题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...

  4. POJ 3177 Redundant Paths 无向图边双联通基础题

    题意: 给一个无向图,保证任意两个点之间有两条完全不相同的路径 求至少加多少边才能实现 题解: 得先学会一波tarjan无向图 桥的定义是:删除这条边之后该图不联通 一条无向边(u,v)是桥,当且仅当 ...

  5. tarjan算法求桥双连通分量 POJ 3177 Redundant Paths

    POJ 3177 Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12598   Accept ...

  6. POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)

    POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...

  7. poj 3177 Redundant Paths(边双连通分量+缩点)

    链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...

  8. [双连通分量] POJ 3177 Redundant Paths

    Redundant Paths Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 13712   Accepted: 5821 ...

  9. POJ 3177 Redundant Paths & POJ 3352 Road Construction(双连通分量)

    Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...

随机推荐

  1. 【BZOJ】【1272】【BeiJingWC2008】Gate of Babylon

    组合数学+容斥原理 Orz zyf-zyf 多重集组合数0.0还带个数限制?  ——>  <组合数学>第6章  6.2带重复的组合 组合数还要模P 0.0? ——> Lucas ...

  2. input点击删除默认value,以及只能输入数字,删除,tab

    /*inputhastip类绑定事件*/ $('.inputhastip').css("color", "#999"); $('.inputhastip').b ...

  3. table 与 div 固定宽高问题

    div {width:100px;height:200px;word-wrap: break-word;overflow:hidden;} 这个可以固定div的宽高,溢出内容会被剪除. table{t ...

  4. c++ 钻石继承

    在C++中,什么叫做钻石问题(也可以叫菱形继承问题),怎么避免它? 下面的图表可以用来解释钻石问题. 假设我们有类B和类C,它们都继承了相同的类A.另外我们还有类D,类D通过多重继承机制继承了类B和类 ...

  5. 【转】System.DateTime.Now.ToString()的一些用法

    C#中的日期处理函数     //2007年4月24日     this.TextBox6.Text = System.DateTime.Now.ToString("D");    ...

  6. rabbitMQ安装及部署

    1.安装 rpm -ivh erlang-18.3-1.el6.x86_64.rpm, 下载地址:http://www.rabbitmq.com/releases/erlang/ rpm --impo ...

  7. VS2010 MFC DataGrid绑定实例

    VS2010环境下MFC使用DataGrid绑定数据源 参考:http://blog.csdn.net/fddqfddq/article/details/7874706 详细介绍如何在MFC中使用Da ...

  8. POJ 3126 Prime Path(BFS求“最短路”)

    题意:给出两个四位数的素数,按如下规则变换,使得将第一位数变换成第二位数的花费最少,输出最少值,否则输出0. 每次只能变换四位数的其中一位数,使得变换后的数也为素数,每次变换都需要1英镑(即使换上的数 ...

  9. [SQL Server系] -- 约束

    什么是约束? 约束(Constraint)是SQL Server中提供的 自动保存数据库完整性 的一种方法,定义了可输入表或表的列中的数据限制条件. SQL Server中共有5中约束 PRIMARY ...

  10. mysql字段的适当冗余有利于提高查询速度

    CREATE TABLE `comment` (  `c_id` int(11) NOT NULL auto_increment COMMENT '评论ID',  `u_id` int(11) NOT ...