之前一直对tarjan算法的这几种不同应用比较混淆...我太弱啦!

被BLO暴虐滚过来

用tarjan求点双,很多神犇都给出了比较详细的解释和证明,在这里就不讲了(其实是这只蒟蒻根本不会orz)

这里放一下定义

这篇博客主要讲一讲求割点,点双的板子实现以及详细解释

先yy这样一道题:

有n个点,m条边,保证给出的是一个联通图,求割点

(真·最裸割点)

这道题就可以用下面这份代码实现

#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<limits.h>
#include<ctime>
#define N 100001
typedef long long ll;
const int inf=0x3fffffff;
const int maxn=2017;
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch>'9'|ch<'0')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return f*x;
}
struct tsdl{
int to,w,next ;
} edge[N*4];
int tot,head[N],dfn[N],low[N],fa[N],son[N],size[N];
bool iscut[N];
void add(int ui,int vi)
{
edge[++tot].next=head[ui];
edge[tot].to=vi;
head[ui]=tot;
}
void tarjan(int x)
{
dfn[x]=low[x]=++tot;
size[x]=1;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa[x])continue;
if(!dfn[v])
{
son[x]++;//x的子树++
fa[v]=x;//v的父亲是x
tarjan(v);
size[x]+=size[v];//x所连节点的个数
low[x]=min(low[x],low[v]);
if(dfn[x]<=low[v])
{
iscut[x]=1;//找到割点
}
}
else low[x]=min(low[x],dfn[v]);
}
if(fa[x]==0&&son[x]<=1)
iscut[x]=0;//根节点,特判处理
}
int main()
{
memset(head,-1,sizeof(head));
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])tarjan(i);
}
for(int i=1;i<=n;i++)
if(iscut[i])cout<<i<<endl;
}

例如我们输入

5 5
1 2
2 3
1 3
3 4
4 5

程序完美の输出了 3,4

是不是很棒啊x

那么我们要统计点双的数量要怎么处理呢?

显然能发现,我们求出一个割点之后,被割点分成的几部分都能分别与这个割点组成一个点双

那么我们只需要统计每个割点被访问次数即可

更改之后的代码:

#pragma GCC optimize("O2")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<limits.h>
#include<ctime>
#define N 100001
typedef long long ll;
const int inf=0x3fffffff;
const int maxn=2017;
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch>'9'|ch<'0')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch<='9'&&ch>='0')
{
x=(x<<3)+(x<<1)+ch-'0';
ch=getchar();
}
return f*x;
}
struct tsdl{
int to,w,next ;
} edge[N*4];
int tot,head[N],dfn[N],low[N],fa[N],son[N],size[N];
bool iscut[N];
void add(int ui,int vi)
{
edge[++tot].next=head[ui];
edge[tot].to=vi;
head[ui]=tot;
}
int ans;
void tarjan(int x)
{
if(iscut[x])ans++;//统计x1
dfn[x]=low[x]=++tot;
size[x]=1;
int tmp=0;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].to==fa[x])continue;
if(!dfn[v])
{
son[x]++;
fa[v]=x;
tarjan(v);
size[x]+=size[v];
low[x]=min(low[x],low[v]);
if(dfn[x]<=low[v])
{
iscut[x]=1;//找到割点
ans++;//统计x2
}
}
else low[x]=min(low[x],dfn[v]);
}
if(fa[x]==0&&son[x]<=1)
iscut[x]=0;//根节点,特判处理
}
int main()
{
memset(head,-1,sizeof(head));
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
int u=read(),v=read();
add(u,v);
add(v,u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])tarjan(i);
}
for(int i=1;i<=n;i++)
if(iscut[i])cout<<i<<endl;
cout<<ans;
}

输出就是直接

当然对他做一点小小的改动也可以实现求桥..

只需要对于每次记录iscut  改为记录二维数组cutedge[x][v]即可

需要注意的是 这里的条件不同于求割点的小于等于 这里需要low[v]严格大于dfn[x]

tarjan求双联通分量(割点,割边)的更多相关文章

  1. tarjan模板 强联通分量+割点+割边

    // https://www.cnblogs.com/stxy-ferryman/p/7779347.html ; struct EDGE { int to, nt; }e[N*N]; int hea ...

  2. tarjan求强联通分量

    tarjan求强联通分量 变量含义说明: pre[i]:i点的被访问的时钟编号,被分配后保持不变 low[i]:i点能访问的最先的点的时钟编号,随子节点改变 scc_no[i]:i点所在的强联通分量的 ...

  3. [J]computer network tarjan边双联通分量+树的直径

    https://odzkskevi.qnssl.com/b660f16d70db1969261cd8b11235ec99?v=1537580031 [2012-2013 ACM Central Reg ...

  4. POJ 3694Network(Tarjan边双联通分量 + 缩点 + LCA并查集维护)

    [题意]: 有N个结点M条边的图,有Q次操作,每次操作在点x, y之间加一条边,加完E(x, y)后还有几个桥(割边),每次操作会累积,影响下一次操作. [思路]: 先用Tarjan求出一开始总的桥的 ...

  5. BZOJ 压力 tarjan 点双联通分量+树上差分+圆方树

    题意 如今,路由器和交换机构建起了互联网的骨架.处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量. 他们每天都生活在巨大的压力之下.小强建立了一个模型.这世界上有N个网络设备, ...

  6. POJ2942 Knights of the Round Table【Tarjan点双联通分量】【二分图染色】【补图】

    LINK 题目大意 有一群人,其中有一些人之间有矛盾,现在要求选出一些人形成一个环,这个环要满足如下条件: 1.人数大于1 2.总人数是奇数 3.有矛盾的人不能相邻 问有多少人不能和任何人形成任何的环 ...

  7. Tarjan求强联通分量+缩点

    提到Tarjan算法就不得不提一提Tarjan这位老人家 Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名.他拥有丰富的商业工作经验,1985年开始任教于普林斯顿大学.Tarj ...

  8. Tarjan算法 (强联通分量 割点 割边)

    变量解释: low 指当前节点在同一强连通分量(或环)能回溯到的dfn最小的节点 dfn 指当前节点是第几个被搜到的节点(时间戳) sta 栈 vis 是否在栈中 ans 指强连通分量的数量 top ...

  9. [hdu2460]network(依次连边并询问图中割边数量) tarjan边双联通分量+lca

    题意: 给定一个n个点m条边的无向图,q个操作,每个操作给(x,y)连边并询问此时图中的割边有多少条.(连上的边会一直存在) n<=1e5,m<=2*10^5,q<=1e3,多组数据 ...

随机推荐

  1. 三.hadoop mapreduce之WordCount例子

    目录: 目录见文章1 这个案列完成对单词的计数,重写map,与reduce方法,完成对mapreduce的理解. Mapreduce初析 Mapreduce是一个计算框架,既然是做计算的框架,那么表现 ...

  2. 【第一部分】01Leetcode刷题

    一.二叉树的中序遍历 题目:94. 二叉树的中序遍历.94. Binary Tree Inorder Traversal 解法一: class Solution { public: vector< ...

  3. 在CI框架中如何实现伪静态

    第一步:在根目录下(index.PHP)同一级目录下建立一个.htaccess这个文件文件内容(即红色标识所显示的内容) URI 类 和 URL 辅助函数 包含了一些函数可以让你更容易的处理 URI ...

  4. Tomcat模型结构

    一.请求过程 Tomca的两大组件:Connecter和Container Connecter组件 1.Connecter将在某个指定的端口上侦听客户请求,接收浏览器的发过来的 tcp 连接请求,创建 ...

  5. nginx的with-http_sub_module模块使用之替换字符串

    一.介绍 该ngx_http_sub_module模块是一个过滤器,通过将一个指定的字符串替换为另一个字符串来修改响应.该模块不是默认生成的,它应该使用--with-http_sub_module 配 ...

  6. 【Android】 textview 中超出屏幕宽度的字符 省略号显示

    当利用textview显示内容时,显示内容过多可能会折行或显示不全,那样效果很不好. 实现如下: <TextView android:layout_width="fill_parent ...

  7. 实际生产用法CMS和G1

    java -Xms100m -Xmx100m -Xmn50m -XX:MetaspaceSize=20m -XX:MaxMetaspaceSize=20m -XX:+UseConcMarkSweepG ...

  8. Python学习(六) —— 函数

    一.函数的定义和调用 为什么要用函数:例如,计算一个数据的长度,可以用一段代码实现,每次需要计算数据的长度都可以用这段代码,如果是一段代码,可读性差,重复代码多: 但是如果把这段代码封装成一个函数,用 ...

  9. BZOJ3560 DZY Loves Math V 数论 快速幂

    原文链接http://www.cnblogs.com/zhouzhendong/p/8111725.html UPD(2018-03-26):蒟蒻回来重新学数论了.更新了题解和代码.之前的怼到后面去了 ...

  10. POJ3076 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的16*16数独,求解. 题解 DLX + 矩阵构建  (两个传送门) 学完这个之后,再 ...