POJ 3177 Redundant Paths (tarjan边双连通分量)
题目连接:http://poj.org/problem?id=3177
题目大意是给定一些牧场,牧场和牧场之间可能存在道路相连,要求从一个牧场到另一个牧场要有至少两条以上不同的路径,且路径的每条path是分立的独立的,意为不能有公共道路,问最少添加多少条道路达成题目的要求。
图论问题,因为题目要求不能有公共道路,就是路径不能有公共边。题目转化为求图的边双连通分量,每个边双连通分量内各个牧场肯定存在不同路径可以相互到达,所以要求出图内有多少个边双连通分量,缩点后添边去满足题意。最终缩点后的图为树,所以最简单的办法就是连接树的叶子节点,答案即为树的(叶子节点个数+1)/2。因为是无向图,所以缩点后找到度为1的节点即为叶子节点。
建双向图,直接跑tarjan求BCC,在求BCC的时候注意是遍历边,而非节点。
#include<iostream>
#include<stack>
#include<vector>
#include<algorithm>
#include<cstring>
using namespace std;
struct node{
vector<int> vex;
vector<int> num;
};
struct edge{
int a,b,id,cut;
}E[5005*2];//a为边的起点,b为边的终点,id为边的输入目录
node g[5005];
int newnode[5005];
int bccnum = 0;
int tot;
int visit[5005],dfn[5005],low[5005];
stack<int> stk;
void tarjan(int x,int fa){
dfn[x] = low[x] = ++tot;
stk.push(x);//节点入栈
for(int i = 0;i<g[x].vex.size() ;i++){
int tedge = g[x].num[i]; //边序号,后续可以由边序号作为索引找到该边的id(目录)
if(visit[tedge]){
continue;
}
visit[tedge] = visit[tedge^1] = 1;//标记双向边已经访问过
if(!dfn[g[x].vex[i]]){
tarjan(g[x].vex[i],x);
low[x] = min(low[x],low[g[x].vex[i]]);
if(low[g[x].vex[i]] > dfn[x] ){
E[tedge].cut = E[tedge^1].cut = 1;//该tedge边为割边,做标记
}
}
else
low[x] = min(low[x],dfn[g[x].vex[i]]);
}
if(dfn[x] == low[x]){
bccnum++;
//找到一个BCC,依次把这个BCC的节点出栈,并做缩点操作
int v;
do
{
v = stk.top() ;
//visit[v] = 0;
stk.pop();
newnode[v] = bccnum;// v节点所属‘bccnum’的边双连通分量
}while(v != x);
}
}
int edgenum = 0;//边的序号从0开始,因为是建立双向边所以两条边标记的序号是异或关系,由边序号可以找到该边的id
void addedge(int u,int v,int id){
E[edgenum].a = u;
E[edgenum].b = v;
g[u].num.push_back(edgenum);
E[edgenum++].id = id;
}
int main(){
int F,R;
cin>>F>>R;
for(int i = 1;i<=R;i++){
int u,v;
cin>>u>>v;
addedge(u,v,i);
addedge(v,u,i);
g[u].vex.push_back(v);
g[v].vex.push_back(u);
}
for(int i = 1;i<=F;i++){
if(!dfn[i]){
tarjan(i,0);
}
}
node newG[bccnum+1];
//cout<<bccnum<<endl;
int mark[bccnum+1];
memset(mark,0,sizeof(mark));
for(int i = 1;i<=F;i++){
for(int j = 0;j<g[i].vex.size() ;j++ ){
if(E[g[i].num[j]].cut ){ //找到了一个割边
mark[newnode[g[i].vex[j]]] ++;//缩点后该BCC的度++
}
}
}
int ans = 0;
for(int i = 1;i<=bccnum;i++){
if(mark[i] == 1){//缩点后度为1的BCC进行统计
//cout<<"x";
ans++;
}
}
cout<<(ans+1)/2;
return 0;
}
POJ 3177 Redundant Paths (tarjan边双连通分量)的更多相关文章
- 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 ...
随机推荐
- 数位dp(模板+例题)
文章参考:数位dp之总结 首先,什么是数位dp?它是干什么的? 数位dp是一种计数用的dp,一般就是要统计一个区间[le,ri]内满足一些条件数的个数. 举个栗子: 加入我们要枚举所有上界不超过231 ...
- 《深入理解java虚拟机》读书笔记二——第三章
第三章 垃圾收集器与内存分配策略 1.判断对象是否已死 引用计数法: 给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1,每当引用失效时,计数器值就减1. 任何时刻计数器为0的对象就是不 ...
- RHEL/CentOS 7中Nginx的systemd service
源码安装的nginx ,没有systemd service 管理 nginx 下面教程,告诉你如何设置nginx 的systemd service nginx systemd的服务文件是/usr/li ...
- 国内下载Git的连接地址
Git国内下载: https://github.com/waylau/git-for-win
- Supervision meeting with Liu
data stream;streampipe/nifi data flow:1. algorithm;;;; top-k pattern, motif and so on 2. implication ...
- Namespace declaration statement has to be the very first statement or after
解决办法:将页面文件转为utp-8无dom格式就OK了.以notepad++为例:
- 如何用python操作XML文件
备注: 基于python3 背景:在统计覆盖率的时候希望绕属性name为test的节点 具体实现源码如下所示,基本都是基于节点属性操作的,当然也就可以基于tag等其他标签去做,可根据需要调整 from ...
- C语言--“.”与“->”有什么区别?
这虽然是个小问题,但有时候很容易让人迷惑,因为有的时候用混淆了,程序编译不通过. 下面说说我对它们的理解. 一般情况下用“.”,只需要声明一个结构体.格式是,结构体类型名+结构体名.然后用结构 ...
- could not parse as expression: "/login" (template: "include/include" - line 32, col 42)
<li><a href="login.html" th:href="/login">登录</a></li> or ...
- 1.spring源码-BeanPostProcessor后置处理器
1.BeanPostProcessor接口的介绍: BeanPostProcessor是一个接口,其中有两个方法,postProcessBeforeInitialization和postProcess ...