Tarjan割点

$Tarjan$求割点

  感觉图论是个好神奇的东西啊,有各种奇奇怪怪的算法,而且非常巧妙。

  周末之前说好回来之后进行一下学术交流,于是wzx就教给我Tarjan,在这里我一定要说: $wzx AK IOI$

  Tarjan发明了很多算法,而且还都叫一个名字,所以说只好用用途来区分它们。

  闲聊时间结束。



  首先,什么是割点呢?在一个无向图中,如果有一个顶点,删除这个顶点以及所有相关联的边以后,图的连通分量增多,就称这个点为割点。

  首先找一个点作为根进行搜索,把图按照$dfs$的方法组织成一棵搜索树,树上的边一定都是图上的边,称为树边,而图上其余的边则为非树边(回边)。

  如果一个点不能通过非树边而回到比他树上的父亲的$dfs$序更小的点,那么如果把它树上的父亲删掉,它就不能通过其他方法与图的其他部分联通,它的父亲就是一个割点。多么神奇啊!对于根节点,我们可以发现,如果它有不止一个的子树,那它就是割点了。看代码:

  

 1 void dfs(int x,int roo,int Dad)
 2 {
 3     id[x]=low[x]=++cnt;
 4     int j,cnts=0;
 5     for (R i=firs[x];i;i=g[i].nex)
 6     {
 7         j=g[i].too;
 8         if(!id[j])
 9         {
10             dfs(j,roo,x);
11             low[x]=min(low[x],low[j]);
12             if(x==roo) cnts++;
13             if(low[j]>=id[x]&&x!=roo) f[x]=1;
14         }
15         else
16         {
17             if(j!=Dad) low[x]=min(low[x],low[j]);
18         }
19     }
20     if(x==roo&&cnts>=2) f[x]=1;
21 }

Tarjan求割点

  这里有一句话还是比较重要的:

 1 if(j!=Dad) low[x]=min(low[x],low[j]);

  是防止重复走树边,其实也可以改成 $low[x]=min(low[x],id[j])$,这样更新出来的$low$可能不是真正的$low$,但是因为儿子到父亲的路径上不会再有别的点,所以这样也能保证正确性。

原文地址:https://www.cnblogs.com/shzr/p/9257813.html

时间: 2024-11-11 09:58:38

Tarjan割点的相关文章

【模板】 Tarjan割点

题目描述 给出一个n个点,m条边的无向图,求图的割点. 输入输出格式 输入格式: 第一行输入n,m 下面m行每行输入x,y表示x到y有一条边 输出格式: 第一行输出割点个数 第二行按照节点编号从小到大输出节点,用空格隔开 输入输出样例 输入样例#1: 6 7 1 2 1 3 1 4 2 5 3 5 4 5 5 6 输出样例#1: 1 5 说明 n,m均为100000 tarjan 图不一定联通!!! 1 #include<iostream> 2 #include<cstdio> 3

Tarjan&amp;割点&amp;割边&amp;点双&amp;边双&amp;缩点

文末有福利. Tarjan是通过搜索树和压栈完成的,维护两个东西:dfn[i](时间戳).low[i](通过搜索树外的边i(返祖边),节点能到达的最小节点的时间戳). 跑完Tarjan,缩点,可以得到DAG图(有向无环图),可以再建图或统计入度出度. 在有向图中,可以找强连通分量SCC(极大强联通子图)(任意两点可以互达): 多维护一个vis[i]表示在不在栈中. 1 void tarjan_(int u) 2 { 3 stack[++tp]=u; 4 dfn[u]=low[u]=++num;

P5058 [ZJOI2004]嗅探器 tarjan割点

这个题是tarjan裸题.最后bfs暴力找联通块就行.(一开始完全写错了竟然得了70分,题意都理解反了...这数据强度...) 题干: 题目描述 某军搞信息对抗实战演习,红军成功地侵入了蓝军的内部网络,蓝军共有两个信息中心,红军计划在某台中间服务器上安装一个嗅探器,从而能够侦听到两个信息中心互相交换的所有信息,但是蓝军的网络相当的庞大,数据包从一个信息中心传到另一个信息中心可以不止有一条通路.现在需要你尽快地解决这个问题,应该把嗅探器安装在哪个中间服务器上才能保证所有的数据包都能被捕获? 输入输

tarjan割点算法代码实现

#include<iostream> using namespace std; int n,m,x,y; int e[9][9]; int root=1; int timex;//时间戳 int num[9],low[9],flag[9];//flag标记割点 int min(int a,int b){ if(a<b){ return a; }else{ return b; } } void dfs(int cur,int father){ int child=0; timex++; n

Tarjan 割点割边【模板】

1 #include <algorithm> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 const int N(100000+15); 8 int n,m,u,v; 9 int head[N],sumedge; 10 struct Edge 11 { 12 int to,next; 13 Edge(int to=0,int next=0) : 14 to(to),next(

Tarjan-求割点

知识点-Tarjan 割点:在一个无向连通图中,如果删掉点 x 后图的连通块数量增加,则称点 为图的割点. 条件: 1)对于搜索树上的非根结点 x ,如果存在子节点 i 满足 F[i]>=D[x]  ,即 i 向上无法达到 x 的祖先,则 x 为割点,这一点比较能够理解. 2)对于搜索树上的根节点x,若它的子节点数 >=2 ,则 x 为割点.说明 i 必须通过 x 节点到达 x 的祖先,这样去掉 x 后,就能分出两个强连通块. 例题 输入 第一行两个整数,n,m,代表点数及边数. 第2行至m+

COGS——T 8. 备用交换机

http://www.cogs.pro/cogs/problem/problem.php?pid=8 ★★   输入文件:gd.in   输出文件:gd.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] n个城市之间有通讯网络,每个城市都有通讯交换机,直接或间接与其它城市连接.因电子设备容易损坏,需给通讯点配备备用交换机.但备用交换机数量有限,不能全部配备,只能给部分重要城市配置.于是规定:如果某个城市由于交换机损坏,不仅本城市通讯中断,还造成其它城市通讯中断,则配

[自用]模板坑待填

Kruskal 最小生成树 重要程度:★★★★☆ 熟练程度:★★★★☆ 代码比较短,还是好理解,就是打的少了点 #include<iostream> #include<cstdio> #include<algorithm> using namespace std; int n,m; struct save { int from;int to;int quan; }cun[10000]; bool aaa(const save &s,const save &

OI分类

黑字:认识 红字:要学 未添加:要学 ├─模拟├─字符串│    ├─字符串基础│    ├─kmp│    ├─trie│    ├─ac自动机│    ├─后缀数组│    └─后缀树├─搜索│    ├─深度搜索(dfs)│    ├─记忆化搜索│    ├─广度搜索(bfs)│    ├─双向广搜│    ├─回溯│    ├─A*│    ├─迭代深搜│    ├─IDA*│    └─dfs序├─动态规划│    ├─区间dp│    ├─环形dp│    ├─背包dp│    ├─