POJ3177 Redundant Paths 图的边双连通分量
题目大意:问一个图至少加多少边能使该图的边双连通分量成为它本身。
图的边双连通分量为极大的不存在割边的子图。图的边双连通分量之间由割边连接。求法如下:
- 求出图的割边
- 在每个边双连通分量内Dfs,标记每个节点所属于的双连通分量编号
- 构建一新图Tree,一个节点代表一个双连通分量。原图中遍历割边,将割边连接的两个双连通分量在Tree中的对应节点连接。
- Tree中算出每个节点的度数,如果一节点度数为1,则其为叶子节点。输出(叶子节点数+1/2)。(连接了叶子节点,就形成了环,Tree中不连接叶子节点的边因为在环内,所以不再是割边了。)
注意:如果一个边是割边,则其反向边也是割边。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <cassert>
using namespace std; #define LOOP(i, n) for(int i=1; i<=n; i++)
const int MAX_NODE = 5010, MAX_EDGE = 10010 * 2; struct G {
struct Node;
struct Edge; struct Node {
int Id, DfsN, Low, InBlock, Degree;
Edge *Head;
}_nodes[MAX_NODE], *Root; struct Edge {
bool IsCut;
Node *From, *To;
Edge *Next, *Rev;
Edge(){}
Edge(Node *from, Node *to, Edge *next):From(from),To(to),Next(next),IsCut(false){}
}*_edges[MAX_EDGE]; int _vCount, _eCount, DfsCnt, BlockCnt, LeafCnt; void Init() {
memset(_nodes, 0, sizeof(_nodes));
_vCount = _eCount = DfsCnt = LeafCnt = 0;
BlockCnt = 0;
} Edge *NewEdge() {
_eCount++;
return _edges[_eCount] ? _edges[_eCount] : _edges[_eCount] = new Edge();
} Edge *AddEdge(Node *from, Node *to) {
Edge *e = NewEdge();
*e = Edge(from, to, from->Head);
from->Head = e;
return e;
} void Build(int uId, int vId, bool is2d) {
while (_vCount < uId || _vCount < vId)
_vCount++;
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *e1 = AddEdge(u, v);
if (is2d) {
Edge *e2 = AddEdge(v, u);
e1->Rev = e2;
e2->Rev = e1;
}
} void FindCutEdge(Node *u, Edge *Prev) {//易忘点:prev
if (u->DfsN)
return;
u->DfsN = u->Low = ++DfsCnt;
for (Edge *e = u->Head; e; e = e->Next) {
if (!e->To->DfsN) {
FindCutEdge(e->To, e);
u->Low = min(u->Low, e->To->Low);
if (u->DfsN < e->To->Low)
e->IsCut = e->Rev->IsCut = true;//易忘点:e->Rev->IsCut
}
else if (e->Rev != Prev)
u->Low = min(u->Low, e->To->DfsN);
}
} void FindCutEdge() {
LOOP(i, _vCount) {//易忘点:图不一定连通,所以要循环。
Root = i + _nodes;
FindCutEdge(Root, NULL);
}
} void SetBlock(Node *u) {
u->InBlock = BlockCnt;
for (Edge *e = u->Head; e; e = e->Next)
if (!e->IsCut && !e->To->InBlock)
SetBlock(e->To);
} void SetBlock() {
LOOP(i, _vCount) {
if (!_nodes[i].InBlock) {
BlockCnt++;
SetBlock(i + _nodes);
}
}
}
void SetLeafCnt() {//此处比较有技巧,注意看看
LOOP(i, _eCount)
_edges[i]->To->Degree++;
LOOP(i, _vCount)
if (_nodes[i].Degree <= 1)
LeafCnt++;
}
}Org, Tree; int main() {
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
//freopen("c:\\noi\\source\\output.txt", "w", stdout);
#endif
Org.Init();
Tree.Init();
int totNode, totEdge, uId, vId;
scanf("%d%d", &totNode, &totEdge);
LOOP(i, totEdge) {
scanf("%d%d", &uId, &vId);
Org.Build(uId, vId, true);
}
Org.FindCutEdge();
Org.SetBlock();
LOOP(i, Org._eCount)
if (Org._edges[i]->IsCut)
Tree.Build(Org._edges[i]->From->InBlock, Org._edges[i]->To->InBlock, false);
Tree.SetLeafCnt();
printf("%d\n", (Tree.LeafCnt + 1) / 2);
return 0;
}
POJ3177 Redundant Paths 图的边双连通分量的更多相关文章
- POJ 3177 Redundant Paths (tarjan边双连通分量)
题目连接:http://poj.org/problem?id=3177 题目大意是给定一些牧场,牧场和牧场之间可能存在道路相连,要求从一个牧场到另一个牧场要有至少两条以上不同的路径,且路径的每条pat ...
- POJ 3177 Redundant Paths (桥,边双连通分量,有重边)
题意:给一个无向图,问需要补多少条边才可以让整个图变成[边双连通图],即任意两个点对之间的一条路径全垮掉,这两个点对仍可以通过其他路径而互通. 思路:POJ 3352的升级版,听说这个图会给重边.先看 ...
- BZOJ1718:[USACO]Redundant Paths 分离的路径(双连通分量)
Description In order to get from one of the F (1 <= F <= 5,000) grazing fields (which are numb ...
- POJ3177 Redundant Paths【tarjan边双联通分量】
LINK 题目大意 给你一个有重边的无向图图,问你最少连接多少条边可以使得整个图双联通 思路 就是个边双的模板 注意判重边的时候只对父亲节点需要考虑 你就dfs的时候记录一下出现了多少条连向父亲的边就 ...
- poj3352 Road Construction & poj3177 Redundant Paths (边双连通分量)题解
题意:有n个点,m条路,问你最少加几条边,让整个图变成边双连通分量. 思路:缩点后变成一颗树,最少加边 = (度为1的点 + 1)/ 2.3177有重边,如果出现重边,用并查集合并两个端点所在的缩点后 ...
- poj3177 Redundant Paths 边双连通分量
给一个无向图,问至少加入多少条边能够使图变成双连通图(随意两点之间至少有两条不同的路(边不同)). 图中的双连通分量不用管,所以缩点之后建新的无向无环图. 这样,题目问题等效于,把新图中度数为1的点相 ...
- POJ3177 Redundant Paths 双连通分量
Redundant Paths Description In order to get from one of the F (1 <= F <= 5,000) grazing fields ...
- POJ3177 Redundant Paths(边双连通分量+缩点)
题目大概是给一个无向连通图,问最少加几条边,使图的任意两点都至少有两条边不重复路径. 如果一个图是边双连通图,即不存在割边,那么任何两个点都满足至少有两条边不重复路径,因为假设有重复边那这条边一定就是 ...
- POJ3177 Redundant Paths —— 边双联通分量 + 缩点
题目链接:http://poj.org/problem?id=3177 Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total ...
随机推荐
- JQuery 使用.show()和.hide()做的可爱动画
只是最基本的东西,没啥稀奇的,只是今天看jquery教程的时候偶然看到show()和hide()是可以写两个参数的, 第一个参数是元素隐藏/显示的速度(单位:毫秒),另一个是一个function类型. ...
- Laravel5.1 学习笔记1, 目录结构和命名空间(待修)
自从用 Laravel4做了个小网站,使用了数据库ORM Eloquent, 就放下了一段时间,想不到这个与Asp.net MVC 有着异曲同工之妙的框架已经出了下个版本,而且还有不小的改动,因此不得 ...
- 如何在Eclipse中创建Web服务器
使用Eclipse开发Web项目时,需要先配置Web服务器,如果已经配置好Web服务器,就不需要再重新配置了.也就是说,本节的内容不是开发每个项目时,都必须经过的步骤.创建Web服务器的具体步骤如下: ...
- Android App 开机启动画面和开机自动启动APP程序设置
1.当前比较成熟一点的应用基本上都会在进入应用之显示一个启动界面 如腾讯微博 2.准备元素 需要开机启动的图片一张 3.新建Activity AlphaAnimation动画:控制对象alpha水平 ...
- c++ 中一个类或者一个对象所占的字节数
转载博客:转载地址https://www.cnblogs.com/JingHuanXiao/p/6080726.html 一个空的class在内存中多少字节?如果加入一个成员函数后是多大?这个成员函数 ...
- 【Oracle】DG三种保护模式及切换方式
一.三种保护方式 Required Redo Transport Attributes for Data Protection Modes Maximum Availability Maximum P ...
- 关于OpenCV的Mat画图问题
由于OpenCV的java版本画图有太多错误,只能自己编写画图的代码,在一个函数中,编写出画圆和深度距离的代码, 代码如下: public int CircleMyMat(Mat Show, Poin ...
- 读白帽子web安全笔记
点击劫持 frame buseting if (top.location != location) { top.location = self.location } html5的sandbox属性 ...
- Everything is a file
"Everything is a file" describes one of the defining features of Unix, and its derivatives ...
- linux backtrace()详细使用说明,分析Segmentation fault
linux backtrace()详细使用说明,分析Segmentation fault 在此之前,开发eCos应用程序时,经常碰到程序挂掉后,串口打印输出一大串让人看不懂的数据.今天才明白,原来这些 ...