题目连接: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. Word报表生成

    /// <summary> /// 生产报表 /// </summary> /// <param name="strTemplate">< ...

  2. 常用命令 在linux下

    1.拷贝某个目录及其下的所有的文件到另外一个目录 语法:cp -r <source directory name>/ <destination directory name>/ ...

  3. sqlserver删除所有表、视图、存储过程

    declare proccur cursor     for         select [name] from sysobjects where type='P' declare @procnam ...

  4. ALSA lib-ext plugin

    参考pcm_speex.c #include <stdio.h> #include <string.h> #include <unistd.h> #include ...

  5. C++——深拷贝

    要实现深拷贝就需要自己编写拷贝构造函数. 深拷贝 #include<iostream> using namespace std; class Point { public:         ...

  6. macaron 根目录默认为templates文件夹,所以如果启动目录同目录下有templates目录,要给它指定另一个文件夹

    m *macaron.Macaron //随便指向一个目录,因为web没用到模板,不能使用默认值templates,因为这个目录被其他模板占用了m.Use(macaron.Renderer(macar ...

  7. 编码 - 调整 gitbash 文本字符集

    概述 gitbash 设置 文本字符集 背景 最近被 编码 的事情搞得乱七八糟 有点没头绪, 所以碰到 编码相关 的东西, 都想看上一看 环境 os win10.1903 git 2.20.1 1. ...

  8. K3修改字段名

    在K3的BOS中,自定义字段之后我们往往会修改字段名,便于记忆和理解,但是修改字段名之后,只是数据库中的字段名被修改了,BOS中的字段标识并没有被修改,可以通过以下语句将标识和字段名改成一致. sel ...

  9. Redis 数据结构的底层实现 (一) RealObject,embstr,sds,ziplist,quicklist

    一.realObject Redis使用 string list zset hash set 五大数据类型来存储键和值.在每次生成一个键值对时,都会生成两个对象,一个储存键一个储存值.redis定义了 ...

  10. centost redhat 卸载rpm以及yum install 的正确姿势

    先看yum  install 的卸载: 第一列为我们要的包名: 那么要移除必须使用 yum list |grep  collectd | awk '{print $1}' |xargs  yum  r ...