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 ...
随机推荐
- [转]微信公众平台WeChat PHP SDK
地址:https://github.com/dodgepudding/wechat-php-sdk 微信公众平台php开发包,细化各项接口操作,支持链式调用 微信支付接入文档: https://mp. ...
- 状态压缩DP---Hie with the Pie
http: //acm.hust.edu.cn/vjudge/contest/view.action?cid=110044#problem/B Description The Pizazz Pizze ...
- Hibernate中的一级缓存、二级缓存和懒加载(转)
1.为什么使用缓存 hibernate使用缓存减少对数据库的访问次数,从而提升hibernate的执行效率.hibernate中有两种类型的缓存:一级缓存和二级缓存. 2.一级缓存 Hibenate中 ...
- 为七牛云存储开发的PHP PEAR 包:Services_Qiniu
七牛云存储Qiniu Resource (Cloud) Storage:用于存储图片.apk等静态资源. 优点: 1.使用七牛带宽和CDN,速度快,不占用开发者服务器. 2.支持图片任意格式.任意分辨 ...
- JS中标准对象
JS中标准对象1:不要使用new Number().new Boolean().new String()创建包装对象:2:用parseInt()或parseFloat()来转换任意类型到number: ...
- udid替代方案
转自http://www.cnblogs.com/zhulin/archive/2012/03/26/2417860.html UDID替代方案 背景: 大多数应用都会用到苹果设备的UDID号,U ...
- python基础之基本算法和装饰器
1.冒泡排序 关于冒泡排序实现大小比较,大索引会向后移动,这次循环将最大数值直接移动至最后. li = [,,,,] ): ]: temp = li[i] li[i] = li[i + ] li[i ...
- 数据库测试DbUnit
DBUnit 的设计理念就是在测试之前,备份数据库,然后给对象数据库植入我们需要的准备数据,最后,在测试完毕后,读入备份数据库,回溯到测试前的状态: 摘自:DbUnit入门实战 DBUnit官网:ht ...
- 一步步学敏捷开发:6、Scrum的3种工件
Scrum的3种工件包括:Product Blacklog.Sprint Backlog.完成标准. 1.产品待办事项列表(Product Backlog) 产品Blacklog是Scrum中的核心工 ...
- 内部类--毕向东Java基础教程学习笔记
内部类的访问规则 1. 内部类可以直接访问外部类的成员,包括私有. 之所以可以直接访问外部类的成员,是因为内部类中持有外部类的引用,格式:外部类名.this 2.外部类要访问内部类,必须建立内部类对象 ...