2021.05.14 tarjan
2021.05.14 tarjan
标准版tarjan
这里使用数组来模拟栈
void tarjan(int x){
++ind;
dfn[x]=low[x]=ind;
stacki[++top]=x;
instack[x]=true;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(dfn[v]==0){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(instack[v]){
low[x]=min(low[x],dfn[v]);//此处可改为low[x]=min(low[x],low[v]);原因如下解释
}
//建议加上if(instacki[v]),否则不在栈中的元素且dfn已更新过的元素会被再一次更新
}
int k=0;
if(dfn[x]==low[x]){
++cnt;
do{
k=stacki[top];
--top;
++num[cnt];
instack[k]=false;
belong[k]=cnt;
}while(k!=x);
}
}
//luougu 2341
直接使用STL
void tarjan(int x){
++ind;
low[x]=dfn[x]=ind;
stacki.push(x);
vis[x]=1;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(vis[v]){
low[x]=min(low[x],low[v]);//此处可改为low[x]=min(low[x],dfn[v]);
}
}
int k=0;
if(low[x]==dfn[x]){
do{
k=stacki.top();
stacki.pop() ;
vis[k]=0;
bl[k]=x;
}while(k!=x);
}
}
缩点
在找到每个点属于哪一个强连通分量以后再建一个图就成,以下为主要代码:
void addi(int u,int v){
++cnt;
ai[cnt].from =u;
ai[cnt].to =v;
ai[cnt].next =headi[u];
headi[u]=cnt;
++in[v];
}
void tarjan(int x){
++ind;
low[x]=dfn[x]=ind;
stacki.push(x);
vis[x]=1;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v);
low[x]=min(low[x],low[v]);
}else if(vis[v]){
low[x]=min(low[x],dfn[v]);
}
}
int k=0;
if(low[x]==dfn[x]){
do{
k=stacki.top();
stacki.pop() ;
vis[k]=0;
bl[k]=x;
sum[x]+=num[k];//题目需要,可删
}while(k!=x);
}
}
int main(){
//中间省略
for(int i=1;i<=n;i++){
if(!dfn[i])tarjan(i);
}
cnt=0;
for(int i=1;i<=m;i++){
if(bl[a[i].from ]!=bl[a[i].to ]){
addi(bl[a[i].from ],bl[a[i].to ]);
}
}
//中间省略
return 0;
}
//luogu 3387
割点
定义:在一个无向图中,如果去掉一个点和它所连出去的的所有边,使得剩下的点不联通(即分成一个以上的强连通分量)时,这个点被称为关节点。关节点也就是割点。
对于根节点:
如图1,当根节点只有一个儿子时,割掉它,剩下的点必然联通,且新的树的个节点为它的儿子;
如图2,当根节点有两个儿子时,割掉它,剩下的点必然不联通(有两个强连通分量)。
对于非根节点:
如图3,点v1,v2均为点u的儿子,我们可以发现(手动模拟,v1和v2不联通),点u为割点。
此时点u存在一个可遍历到的后代v1,且点v1无法走回点u的前辈,满足该性质。
我们在v1,v2间加上一条边。
如图4,此时我们可以发现点u并不为割点(此时v1,v2和点u的前辈联通)。
此时点u存在一个可遍历到的后代v1,且点v1,v2都可以走回点u的前辈,不满足该性质。
void tarjan(int x,int root){
int child=0;
++ind;
low[x]=dfn[x]=ind;
for(int i=head[x];i;i=a[i].next ){
int v=a[i].to ;
if(!dfn[v]){
tarjan(v,x);
low[x]=min(low[x],low[v]);
if(low[v]>=dfn[x]&&x!=root)cut[x]=1;
if(x==root)++child;
}
low[x]=min(low[x],dfn[v]);//此处不可以改为low[x]=min(low[x],low[v]);解释如下
}
if(root==x&&child>=2)cut[x]=1;
}
int main(){
//中间省略
for(int i=1;i<=n;i++)
if(!dfn[i])tarjan(i,i);
for(int i=1;i<=n;i++)
if(cut[i])++ans;
//中间省略
}
//luogu 3388
关于low[x]=min(low[x],low[v])和low[x]=min(low[x],dfn[x])的问题
标准版tarjan和缩点需要判断点在不在强连通分量中以及在哪个强连通分量中,所以一个点可以重复更新low[x]=min(low[x],dfn[v]),如果在同一个强连通分量中,迟早会遍历到起点,况且instacki[]或vis[]数组就是为了判断这个点在不在栈中。
而割点只需要寻到这个点能到达的且不是从来时的边到达的最早的节点,这个最早的节点可以和另一个更早的节点相连,设最早的节点为fa,更早的节点为grandpa,这个节点为son,则low[fa]==low[grandpa]&&dfn[fa]!=dfn[grandpa],我们只需要使low[son]=dfn[fa]而不是使low[x]=low[grandpa]。
参考题解 P3388 【【模板】割点(割顶)】 - Michael_Li 的博客 - 洛谷博客 (luogu.com.cn)
2021.05.14 tarjan的更多相关文章
- java selenium启动火狐浏览器报错:Cannot find firefox binary in PATH. Make sure firefox is installed. OS appears to be: VISTA Build info: version: '3.8.1', revision: '6e95a6684b', time: '2017-12-01T19:05:14.666Z
Cannot find firefox binary in PATH. Make sure firefox is installed. OS appears to be: VISTA Build in ...
- 2021.11.14 CF1583E Moment of Bloom(LCA+图上构造)
2021.11.14 CF1583E Moment of Bloom(LCA+图上构造) https://www.luogu.com.cn/problem/CF1583E 题意: She does h ...
- 2021.05.03 T3 数字
2021.05.03 T3 数字 问题描述 一个数字被称为好数字当他满足下列条件: 1. 它有**2*n**个数位,n是正整数(允许有前导0) 2. 构成它的每个数字都在给定的数字集合S中. 3. 它 ...
- Noip模拟53 2021.9.14
T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...
- 寻找大学目标及行动步骤——记ITAEM团队第二期宣讲会(2014.05.14)
·昨晚8:00-9:40.在 钟海楼03029 ,进行了ITAEM团队第二期宣讲会(第一期见第一期宣讲会总结).来參加的主要是大一学生.以信院为主.也有法学院.文学院的同学. 在宣讲会中,大家都比較积 ...
- OpenSpiel 随笔 05.14
------------恢复内容开始------------ 这两天年总算把自己的游戏写完了,也通过了所有的测试. 我将自己的代码上传到了我的github上, 地址是 https://github.c ...
- Noip模拟76 2021.10.14
T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...
- Noip模拟39 2021.8.14
T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...
- Noip模拟15 2021.7.14
T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...
随机推荐
- 一个tomcat部署两个springboot服务时启动JMX报错
一.问题来源 今天在部署开发好的组件的时候,发现无法启动,检查启动日志,报如下错误: 2022-03-17T10:39:41.823+08:00 ERROR vediomanage.vediomana ...
- Spring Boot 需要独立的容器运行吗?
可以不需要,内置了 Tomcat/ Jetty 等容器.
- maven-something
<!--dependencyManagement提供一种管理依赖版本好的方式--> <!-- 通常出现在项目的最顶层父POM,--> <!-- 可以让所有在子项目中引用的 ...
- FiddlerEverywhere注册账号进行激活失效问题
有关FiddlerEverywhere通过邮件激活账号时,激活链接提示已失效问题:这个链接有进行一个讨论(https://www.telerik.com/forums/unable-to-activa ...
- centos简单命令备忘
1.查看当前目录 [root@instance-aif30iaj bin]# df -h 2.查看指定目录 在命令后直接放目录名,比如查看"usr"目录使用情况: [root@in ...
- JavaScript的取值小技巧之“中括号[]取值法”
一.简介 做下记录,今天看了一篇很有意思的文章,学到了这个取值的小技巧 正常的话我们一般都是用对象直接去'.'对应的属性名(也就是键值对的键)来获取对应的值 这里记录的是另一种取值方式,他是采用中括号 ...
- python学习笔记(五)——静态方法、类方法、运算符重载
我们都知道类名是不能够直接调用类方法的.在C++中,把成员方法声明为 static 静态方法后可以通过类名调用.同样的在python中也可以通过定义静态方法的方式让类名直接调用. 静态方法 使用 @s ...
- vue2源码框架和流程分析
vue整体框架和主要流程分析 之前对看过比较多关于vue源码的文章,但是对于整体框架和流程还是有些模糊,最后用chrome debug对vue的源码进行查看整理出这篇文章.... 本文对vue的整体框 ...
- 来扯点ionic3[7] LocalStorage的使用—以登录和注销为例
一般意义上,一个互联网 APP 中的数据主自与服务器的交互,但是对于有些数据,我们希望获取到它们以后能保存,并在全局环境使用,比如用户数据--我们不希望在每个页面都从服务器拉取一遍.这时我们就可以利用 ...
- 现代CSS进化史
英文:https://medium.com/actualize-...编译:缪斯 CSS一直被web开发者认为是最简单也是最难的一门奇葩语言.它的入门确实非常简单--你只需为元素定义好样式属性和值,看 ...