tarjan算法求桥双连通分量 POJ 3177 Redundant Paths
POJ 3177 Redundant Paths
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 12598 | Accepted: 5330 |
Description
Given a description of the current set of R (F-1 <= R <= 10,000) paths that each connect exactly two different fields, determine the minimum number of new paths (each of which connects exactly two fields) that must be built so that there are at least two separate routes between any pair of fields. Routes are considered separate if they use none of the same paths, even if they visit the same intermediate field along the way.
There might already be more than one paths between the same pair of fields, and you may also build a new path that connects the same fields as some other path.
Input
Lines 2..R+1: Each line contains two space-separated integers which are the fields at the endpoints of some path.
Output
Sample Input
7 7
1 2
2 3
3 4
2 5
4 5
5 6
5 7
Sample Output
2
Hint
One visualization of the paths is:
1 2 3
+---+---+
| |
| |
6 +---+---+ 4
/ 5
/
/
7 +
Building new paths from 1 to 6 and from 4 to 7 satisfies the conditions.
1 2 3
+---+---+
: | |
: | |
6 +---+---+ 4
/ 5 :
/ :
/ :
7 + - - - -
Check some of the routes:
1 – 2: 1 –> 2 and 1 –> 6 –> 5 –> 2
1 – 4: 1 –> 2 –> 3 –> 4 and 1 –> 6 –> 5 –> 4
3 – 7: 3 –> 4 –> 7 and 3 –> 2 –> 5 –> 7
Every pair of fields is, in fact, connected by two routes.
It's possible that adding some other path will also solve the problem (like one from 6 to 7). Adding two paths, however, is the minimum.
/*这是一个63分的代码,因为没有注意到题目中的重边问题,以后要注意有重边的图和没有重边的图的tarjan求桥的算法,是不同的*/
#include<iostream>
using namespace std;
#include<cstdio>
#define N 5001
#define R 10010
#include<stack>
#include<queue>
#include<cstring>
queue<int>que;
bool qiao[R]={},visit[N]={},visit_edge[R<<];
struct Edge{
int u,v,last;
}edge[R*];
int head[N],du[N],f,r,father[N],dfn[N],low[N],topt=,t=-;
int ans[N]={};
void add_edge(int u,int v)
{
++t;
edge[t].u=u;
edge[t].v=v;
edge[t].last=head[u];
head[u]=t;
}
void input()
{
memset(head,-,sizeof(head));
int u,v;
scanf("%d%d",&f,&r);
for(int i=;i<=r;++i)
{
scanf("%d%d",&u,&v);
add_edge(u,v);
add_edge(v,u);
}
r<<=;
}
void tarjan(int u)
{
dfn[u]=low[u]=++topt;
for(int l=head[u];l!=-;l=edge[l].last)
{
int v=edge[l].v;
if(!visit_edge[l]&&!visit_edge[l^])
{
visit_edge[l]=true;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u]) qiao[l]=true;
}
else low[u]=min(low[u],dfn[v]);
}
}
}
void suo_dian()
{
for(int i=;i<=f;++i)
{
if(!visit[i])
{
ans[++ans[]]=i;
que.push(i);
visit[i]=true;
while(!que.empty())
{
int x=que.front();
father[x]=i;
que.pop();
for(int l=head[x];l!=-;l=edge[l].last)
{
if(qiao[l]||visit[edge[l].v]) continue;
que.push(edge[l].v);
visit[edge[l].v]=true;
}
} }
}
}
void re_jiantu()
{
for(int l=;l<=r;++l)
{
if(father[edge[l].u]!=father[edge[l].v])
{
du[father[edge[l].u]]++;
du[father[edge[l].v]]++;
}
}
}
int main()
{
freopen("rpaths.in","r",stdin);
freopen("rpaths.out","w",stdout);
input();
for(int i=;i<=f;++i)
{
if(!dfn[i])
tarjan(i);
}
suo_dian();
re_jiantu();
int sum=;
for(int i=;i<=ans[];++i)
if(du[ans[i]]==)
sum++;
printf("%d\n",(sum+)/);
fclose(stdin);fclose(stdout);
return ;
}
正确代码及模板:
#define N 5011
#include<iostream>
using namespace std;
#define M 10010
#include<cstdio>
#include<cstring>
struct Gra{
int n,m,ans,head[N],topt,dfn[N],low[N],t,cnt[N];
bool visit[M<<];
struct Edge{
int v,last;
}edge[M<<];
void init(int f,int r)
{/*初始化不要在上面,上面只是声明,不是变量*/
ans=,topt=,t=-;
n=f;m=r;
memset(head,-,sizeof(head));
memset(dfn,,sizeof(dfn));
memset(low,,sizeof(low));
memset(cnt,,sizeof(cnt));
memset(visit,false,sizeof(visit));
}
void add_edge(int x,int y)
{
++t;
edge[t].v=y;
edge[t].last=head[x];
head[x]=t;
}
void tarjan(int u)
{
dfn[u]=low[u]=++topt;
for(int l=head[u];l!=-;l=edge[l].last)
{
if(visit[l]) continue;
visit[l]=visit[l^]=true;/*找到无向边拆成的另一条边*/
int v=edge[l].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[v],low[u]);
}
else low[u]=min(low[u],dfn[v]);/*多次返祖*/
}
}
void start()
{
for(int i=;i<=n;++i)
if(!dfn[i])
tarjan(i);
for(int i=;i<=n;++i)/*处理缩点以后的图*/
for(int l=head[i];l!=-;l=edge[l].last)
{
int v=edge[l].v;
if(low[i]!=low[v])
cnt[low[v]]++;
/*low[x]!=low[y]说明从low[y]回不到low[x],那么low[x]--low[y]是一条桥,因为tarjan中多次返祖*/
}
for(int i=;i<=n;++i)
if(cnt[i]==) ans++;/*统计度数是1的叶子节点的数目*/
printf("%d\n",(ans+)>>);
}
}G;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
G.init(n,m);
int x,y;
for(int i=;i<=m;++i)
{
scanf("%d%d",&x,&y);
G.add_edge(x,y);
G.add_edge(y,x);
}
G.start();
return ;
}
tarjan算法求桥双连通分量 POJ 3177 Redundant Paths的更多相关文章
- [双连通分量] 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(双连接)
POJ 3177 Redundant Paths POJ 3352 Road Construction 题目链接 题意:两题一样的.一份代码能交.给定一个连通无向图,问加几条边能使得图变成一个双连通图 ...
- POJ 3177 Redundant Paths (桥,边双连通分量,有重边)
题意:给一个无向图,问需要补多少条边才可以让整个图变成[边双连通图],即任意两个点对之间的一条路径全垮掉,这两个点对仍可以通过其他路径而互通. 思路:POJ 3352的升级版,听说这个图会给重边.先看 ...
- poj 3177 Redundant Paths(边双连通分量+缩点)
链接:http://poj.org/problem?id=3177 题意:有n个牧场,Bessie 要从一个牧场到另一个牧场,要求至少要有2条独立的路可以走.现已有m条路,求至少要新建多少条路,使得任 ...
- POJ 3177 Redundant Paths(边双连通分量)
[题目链接] http://poj.org/problem?id=3177 [题目大意] 给出一张图,问增加几条边,使得整张图构成双连通分量 [题解] 首先我们对图进行双连通分量缩点, 那么问题就转化 ...
- [学习笔记] Tarjan算法求桥和割点
在之前的博客中我们已经介绍了如何用Tarjan算法求有向图中的强连通分量,而今天我们要谈的Tarjan求桥.割点,也是和上篇有博客有类似之处的. 关于桥和割点: 桥:在一个有向图中,如果删去一条边,而 ...
- POJ 3177 Redundant Paths (tarjan边双连通分量)
题目连接:http://poj.org/problem?id=3177 题目大意是给定一些牧场,牧场和牧场之间可能存在道路相连,要求从一个牧场到另一个牧场要有至少两条以上不同的路径,且路径的每条pat ...
- poj 3177 Redundant Paths【求最少添加多少条边可以使图变成双连通图】【缩点后求入度为1的点个数】
Redundant Paths Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 11047 Accepted: 4725 ...
- 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 ...
随机推荐
- 在博客中使用MathJax写数学公式
前言 总结一些在博客园使用MathJax写数学公式的经验. 博客园 设置使用数学公式 进入你的博客:管理 > 选项 里面有个启用数学公式支持,选上后保存. 这时,你就可以在你的博客里写数学公式了 ...
- jQuery owlcarousel 旋转木马
owlcarousel是一款猫头鹰旋转木马插件.OwlCarousel优势兼容所有浏览器支持响应式支持 CSS3 过度支持触摸事件支持 JSON 及自定义 JSON 格式支持进度条支持自定义事件支持延 ...
- 字母排序问题(c++实现)
描述:编写一个程序,当输入不超过60个字符组成的英文文字时,计算机将这个句子中的字母按英文字典字母顺序重新排列,排列后的单词的长度要与原始句子中的长度 相同.例如: 输入: THE PRICE OFB ...
- mongodb driver c#语法
Definitions and BuildersThe driver has introduced a number of types related to the specification of ...
- VisualStudio中解决方案
在VS中创建一个项目通常会生成一个解决方案文件(.sln)和一个隐藏的解决方案用户选项文件(.suo). 解决方案文件是一个文本文件,包含以下信息: 将被加载的所有项目以构成完整解决方案的项目清单 解 ...
- 实验12:Problem G: 强悍的矩阵运算来了
这个题目主要是乘法运算符的重载,卡了我好久,矩阵的乘法用3个嵌套的for循环进行,要分清楚矩阵的乘法结果是第一个矩阵的行,第二个矩阵的列所组成的矩阵. 重载+,*运算符时,可以在参数列表中传两个矩阵引 ...
- SharedPreference.Editor的apply和commit方法异同
这两个方法的区别在于: 1. apply没有返回值而commit返回boolean表明修改是否提交成功 2. apply是将修改数据原子提交到内存, 而后异步真正提交到硬件磁盘, 而commit是同步 ...
- Android项目实战(二):安卓应用程序退出的三种方法
现在的APP退出的时候都不是让用户点击了“后退键”就退出.防止用户点错了后退键而造成的用户体检不好. 一年前搞的Demo代码不见了,重新写下就当是复习和以后直接拿来用把 目前流行的解决一般分为两种: ...
- JAVA基础学习day14--集合一
一.集合的出现 1.1.集合简述 面向对象语言对事物的体现都是以对象形式,为了方便对多个对象的操作,就对象对象进行存储,集合就是存仪储对象最常用的一种试 1.2.数组和集合都是容器 数组也存对象,存储 ...
- UnityShader之Shader格式篇【Shader资料1】
关于Shader,在Unity里面我们一般叫做ShaderLab,只要你的职业是与渲染搭边,Unity就与ShaderLab有着直接的关联,你都应该试着去学会它,其实我们在新手未有入门的时候,我们总是 ...