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 ...
随机推荐
- B - Substrings Sort
Problem description You are given nn strings. Each string consists of lowercase English letters. Rea ...
- Kali linux 2016.2(Rolling)之 Nessus安装及Plugins Download Fail 解决方法
最近,因科研需要,学习Nessus. Nessus是一款优秀的漏洞扫描软件,在其v6 HOME版本中在线更新漏洞插件不成功,采用离线更新,成功地更新了插件,在此将更新方法进行分享. 1.Nessus软 ...
- lnmp 安装FTP服务 并配置FTP用户
lnmp 默认是不带FTP服务的,需要的童鞋要自行安装.步骤也很简单 一,进入lnmp目录,找到pureftpd.sh 二,直接运行该脚本 ./pureftpd.sh 按任意键开始安装,等待,安装成功 ...
- DeltaFish 校园物资共享平台 第一次小组会议
软工小组第一次会议 会议地点:图书馆 会议时间:19:00 ~ 20:00 与会人员:软工小组全体成员 请假人员:无缺席人员:无 记录人:陈志锴 整理人:曾子轩 会议记录 一.确认选题 每一位成员提出 ...
- postgreSQL中跨库查询在windows下的实现方法
以下是在postgreSQL 8.1版本中的实践,其他版本类似: 1.将C:\Program Files\PostgreSQL\8.1\share\contrib下的dblink.sql复制到C:\P ...
- 2星|《工业X.0》:物联网的资料汇编
工业X.0:实现工业领域数字价值 看完比较失望,没有看到新的观点想法.基本算是物联网的资料汇编.总体评价2星. 以下是书中一些内容的摘抄: 1:例如,埃森哲为其员工开发了一个用例,用增强现实技术解决实 ...
- Java RMI之HelloWorld经典入门案例
Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...
- 【转】虚拟化(三):vsphere套件的安装注意及使用
vsphere套件里面主要的组件有esxi.vcenter server .vsphere client和vsphere web client. vcenter做为vsphere套件的核心管理成员之一 ...
- S-HR界面控件赋值取值
属性值: this.getField("entrys.variationReason").shrPromptBox("getValue").name
- EasyUI 解决Js动态加载页面样式不显示问题
var strHtml = "<input name='mydate' class='easyui-datebox'>"; 直接使用append把内容加载到页面中,Ea ...