POJ 3177 Redundant Paths (桥,边双连通分量,有重边)
题意:给一个无向图,问需要补多少条边才可以让整个图变成【边双连通图】,即任意两个点对之间的一条路径全垮掉,这两个点对仍可以通过其他路径而互通。
思路: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 (桥,边双连通分量,有重边)的更多相关文章
- POJ 3177 Redundant Paths(边双连通分量)
[题目链接] http://poj.org/problem?id=3177 [题目大意] 给出一张图,问增加几条边,使得整张图构成双连通分量 [题解] 首先我们对图进行双连通分量缩点, 那么问题就转化 ...
- POJ 3177 Redundant Paths(边双连通的构造)
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13717 Accepted: 5824 ...
- POJ - 3177 Redundant Paths (边双连通缩点)
题意:在一张图中最少可以添加几条边,使其中任意两点间都有两条不重复的路径(路径中任意一条边都不同). 分析:问题就是最少添加几条边,使其成为边双连通图.可以先将图中所有边双连通分量缩点,之后得到的就是 ...
- POJ 3177 Redundant Paths 无向图边双联通基础题
题意: 给一个无向图,保证任意两个点之间有两条完全不相同的路径 求至少加多少边才能实现 题解: 得先学会一波tarjan无向图 桥的定义是:删除这条边之后该图不联通 一条无向边(u,v)是桥,当且仅当 ...
- tarjan算法求桥双连通分量 POJ 3177 Redundant Paths
POJ 3177 Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 12598 Accept ...
- POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...
- poj 3177 Redundant Paths(边双连通分量+缩点)
链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...
- [双连通分量] POJ 3177 Redundant Paths
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 13712 Accepted: 5821 ...
- 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 ...
随机推荐
- NYOJ-32 组合数 AC 分类: NYOJ 2014-01-02 22:21 112人阅读 评论(0) 收藏
#include<stdio.h> int num[100]; int pnum(int n,int v); int mv=0; int main(){ int n,v; scanf(&q ...
- error: The shader requires a sampler in slot 0 which hasn't been set [XXXsampler]
About the sampler, you need to assign it to your pixelshader. m_d3dContext.Get()->PSSetSamplers(0 ...
- PE文件结构详解(四)PE导入表
PE文件结构详解(二)可执行文件头的最后展示了一个数组,PE文件结构详解(三)PE导出表中解释了其中第一项的格式,本篇文章来揭示这个数组中的第二项:IMAGE_DIRECTORY_ENTRY_IMPO ...
- synergy--共享你的键鼠
synergy用来分享一套键鼠,作用于多台主机.可作用于linux.Windows和mac平台.工作方式是:将一台主机作为服务器端,然后服务器端将会分享自己的键鼠,另一台主机作为客户端连接服务端就可以 ...
- 【面试题013】在O(1)时间删除链表结点
[面试题013]在O(1)时间删除链表结点 我们要删除结点i,我们可以把结点i的下一个结点j的内容复制到结点i,然后呢把结点i的指针指向结点j的下一个结点.然后在删除结点j. 1.如果结点i位于链表 ...
- Eclipse通过集成svn实现版本控制
Eclipse通过集成svn即安装subclipse插件 前面已经讲解过了,这就不说了,作为测试人员继续总结下Eclipse通过集成svn实现的版本控制 首次从SVN代码库中导出代码文件: 1.右键工 ...
- 【转载】jxl操作excel 字体 背景色 合并单元格 列宽等 .
package com.email.jav; import java.io.File;import java.io.IOException;import java.net.URL; import jx ...
- 前端H5开发工具 Adobe Edge
http://www.cnblogs.com/adobeedge/ http://my.oschina.net/duolus/blog/212801?fromerr=WAcqscJl
- linux入门教程(七) linux系统用户以及用户组管理
关于这部分内容,笔者在日常的linux系统管理工作中用到的并不多,但这并不代表该内容不重要.毕竟linux系统是一个多用户的系统,每个账号都干什么用,你必须了如指掌.因为这涉及到一个安全的问题. [认 ...
- 使用post()方法以POST方式从服务器发送数据
使用post()方法以POST方式从服务器发送数据 与get()方法相比,post()方法多用于以POST方式向服务器发送数据,服务器接收到数据之后,进行处理,并将处理结果返回页面,调用格式如下: $ ...