题目连接: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边双连通分量)的更多相关文章

  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. Django 查看原生的sql语句

    python manage.py sqlmigrate your_app_name 0001 把your_app_name换成自己的app名字即可看到框架自动生成的创建表sql语句,于是我就这样看到了 ...

  2. H5_0017:通过元素自定义属性值获取元素对象,并获取属性值

            // 通过元素的属性值查找对象         // document.querySelectorAll("[data]").forEach(function(e) ...

  3. bookdown学习笔记

    主要参考大佬谢益辉的bookdown学习笔记 https://bookdown.org/yihui/bookdown/pandoc.html 灰常之详细 然后clone了他写好的小demo,准备自己试 ...

  4. mysql 数据库基础操作

    一 知识储备 MySQL数据库基本操作知识储备 数据库服务器:一台计算机(对内存要求比较高) 数据库管理系统:如mysql,是一个软件 数据库:oldboy_stu,相当于文件夹 表:student, ...

  5. TCL 包

    包用于创建代码的可重用单元. 程序包提供特定功能的文件集合. 1.创建代码 2.创建包index 打开tclsh,切换到HelloWorld目录,并使用pkg_mkindex 命令创建索引文件. %c ...

  6. sql server和my sql 命令(语句)的区别,sql server与mysql的比较

    sql与mysql的比较 1.连接字符串sql  :Initial Catalog(database)=x;  --数据库名称      Data Source(source)=x;        - ...

  7. ECMAScript基本语法——④变量

    简介 变量:一小块存储数据的内存空间先申请了一块内存空间,规定空间的存储类型,给空间赋值3, 想找到这个3可以通过内存空间的地址值,但是通过地址值太麻烦了,给这个空间起了一个名字a 通过这个a可以找到 ...

  8. python面试的100题(13)

    29.Given an array of integers 给定一个整数数组和一个目标值,找出数组中和为目标值的两个数.你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用.示例:给定nums ...

  9. vue的一些基础知识点,后续会更新最全的vue知识点

    axios中jq的基础 jq语法 $(this).hide() 隐藏当前的html元素 $(''#test").hide() 隐藏id='test'的元素 添加新的 HTML 内容 我们将学 ...

  10. AcWing 1013. 机器分配

    //分组背包 for物品 for体积 for 决策 #include <iostream> using namespace std; ; int n, m; int w[N][N]; in ...