文章目录

  • 割点(无向图).
  • 总结:
    • 割点算法实现模拟
    • 题解
    • 思考
    • 再来一题

割点(无向图).

P3388 【模板】割点(割顶)题目链接:洛谷
tarjan遍历过程视频链接

总结:

1.图用dfs的遍历。dfs对图,就会形成树 (写dfs代码时刻要有""的思想)
2.Tarjan算法求非强连通图,主要用到了两个数组,dfn和low数组。
3.在dfs中如何加东西:
dfs(i)后面语句怎么写?每次dfs完成后,就是对前面的影响,
像栈一样。
4.无向图实际是 在无向树的基础上节点添加边。
连通图定义:
在无向图中,一个连通图中任意两点均可到达,称为连通图。
割点的定义:
在一个无向图里,去掉一个顶点,及其去掉该点的所有边,剩下的图
不连通,那么这个点就是个割点。
割边的定义: (不会不会,以后再补 。)
在一个无向图里,去掉一条边,图就不连通了。
举个栗子:下图的无向图的割点为:0,3。

割点算法实现模拟

ps:以下两图来自上文视频链接截下来的图
在下图 上面数字dfn数组,下面数字low数组。
用了一个栈更好理解。
其中满足low[u]=dfn[u],退栈到u.
dfn中是时间戳是,1-2-3-4
然后回退到2 , 2-5
再回退到1, 1到6.
最后回退到1.结束。

强连通分量怎么就有了呢?
在退栈2时,进栈5,判断1时,low[5]=dfn[1];
之后在5中退出。
有个5-1,形成了一个1-2-5-1的环,这不就成了一个强连通分量了。

之后就是这么执行。

下面图举例(方便理解后续的代码): 我画成树的样子,再在节点随意连,就成了无向图。
1号是该的根节点 :那么子节点是两个, 就不是三个了?
为什么呢?
原因是: 我们在遍历的时候深度搜索,搜到3时,3就搜到4,4被标记了,退回到1节点,4节点已经标记了,1节点就不会对4搜。
所以1节点的子节点是2个。

所以只要根节点的子节点有两个及以上,根节点就是割点。(这里的子节点要细心些)。

题解

样例输入:
上图。
题解代码如下
代码如下:
割点针对无向图!!

#include<iostream>
#include<vector>
#include<set>
using namespace std;
int read(){int s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}const int maxn=2e5+3;
int low[maxn],dfn[maxn]; //dfn:"时间戳"
int visit[maxn]; //点的有无访问
int index;
vector<int> a[maxn]; //邻接表
int fa[maxn]; //
set<int> s;
inline void tarjan(int u){int sum=0;visit[u]=1;  dfn[u]=low[u]=++index;for(int i=0;i<a[u].size();i++){int v=a[u][i]; //u到v。if(!visit[v]){fa[v]=u; // 父亲节点用来判断起始点sum++;tarjan(v);//u后面的dfs完成了,执行下面语句时在v顶点要做的事都完成了//现在开始完成u的事,根据v的事完成u的事。low[u]=min(low[u],low[v]);//先把起始点排除.if(fa[u]!=u&&low[v]>=dfn[u]) s.insert(u);} else //if(v!=fa[u]) low[u]=min(low[u],dfn[v]);//dfn[v] 会更好些,有点像能唯一确定他组成一个环的先祖吧//low[v] 写起也怪怪的}//根特判定的原因,根就没先祖了,也就用不了low,dfn判定了。//判断是无割点:子节点两个及以上就是割点。if(fa[u]==u&&sum>=2) s.insert(u);
}
int main (){int n,m;n=read();m=read();int u,v;for(int i=1;i<=m;i++){u=read();v=read();a[u].push_back(v);a[v].push_back(u);}for(int i=1;i<=n;i++){if(!visit[i]){fa[i]=i;//父节点赋初值tarjan(i);index=0;}}cout<<s.size()<<endl;for(set<int>::iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}return 0;
}

思考

思考一下没s.insert(u),u会不会被重复的添加呢?
没错,当然会重复咯,不然为啥用set集合呢!,是吧 。
改一下tarjan函数
如下:
那就用ans数组记录下每个割点加了几次。

int ans[maxn];
inline void tarjan(int u){int sum=0;int num=0;visit[u]=1;dfn[u]=low[u]=++index;for(int i=0;i<a[u].size();i++){int v=a[u][i];if(!visit[v]){fa[v]=u;sum++;tarjan(v);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]) {num++;s.insert(u);//cout<<u<<"end"<<endl;}} else //if(v!=fa[u]) low[u]=min(low[u],dfn[v]);}//if(fa[u]==u&&sum>=2) {num++;s.insert(u);}if(fa[u]!=u) num++;//if(u==1) cout<<num<<endl;ans[u]=num;
}

ans数组结果如下 2 1 2 2 1 2

咦!!!!细心的你发现了,咋就1加了两次呢???
原来顶点1是树的根呀(dfs嘛,就是图的遍历,那就树咯),1都是根了,就没有父节点。low[1]=dfn[1]=1; 所以会加一次。
这就是为啥在题解代码里会有对根节点的特判。
那么根节点怎么才能是割点呢。问到点子上了。

再来一题

2020小米选拔赛第一场D题:Router Mesh

题意:
无向图n点m边
删除任意一点后,有多少个连通图
思路
首先得知道图不一定是连通的喔。就会牵扯到有好几个连通图。
上文也讲到了ans数组。
嗯哼,派上用场啦..................
删除一点,那他的所有边也会被删掉。那会增加几个连通图呢??
那不得增加ans[i]个咯。

题解代码如下:

#include<iostream>
#include<vector>
#include<set>
using namespace std;
int read(){int s = 0, f = 1; char ch = getchar();while(!isdigit(ch)){if(ch == '-') f = -1;ch = getchar();}while(isdigit(ch)) s = (s << 3) + (s << 1) + (ch ^ 48), ch = getchar();return s * f;
}
const int maxn=4e5+3;
int low[maxn],dfn[maxn];
int visit[maxn];
int index;
vector<int> a[maxn];
int fa[maxn];
set<int> s;
int ans[maxn];
inline void tarjan(int u){int sum=0;int num=0;visit[u]=1;dfn[u]=low[u]=++index;for(int i=0;i<a[u].size();i++){int v=a[u][i];if(!visit[v]){//删去了对根节点的特判,根节点会进入s集合里,如果他不是割点就只进一次。fa[v]=u;sum++;tarjan(v);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]) {num++;s.insert(u);}} else //if(v!=fa[u]) low[u]=min(low[u],dfn[v]);}//if(fa[u]==u&&sum>=2) {num++;s.insert(u);}//为啥要在这样还要num++呢,嗯。。。玄学。if(fa[u]!=u) num++;//if(u==1) cout<<num<<endl;ans[u]=num;
}
int main (){int n,m;n=read();m=read();int u,v;for(int i=1;i<=m;i++){u=read();v=read();a[u].push_back(v);a[v].push_back(u);}int num=0;for(int i=1;i<=n;i++){if(!visit[i]){num++;fa[i]=i;tarjan(i);index=0;}}/*cout<<s.size()<<endl;for(set<int>::iterator i=s.begin();i!=s.end();i++){cout<<*i<<" ";}*///cout<<num<<endl;for(int i=1;i<=n;i++){//在这里ans[i]减了1 //对应了这条代码if(fa[u]!=u) num++;//也就是根节点不加,非根节点要加1。cout<<ans[i]-1+num<<" ";}return 0;
}

割点(tarjan算法)相关推荐

  1. POJ 2117 Electricity 割点 Tarjan算法

    [题意] 选择去掉无向图中的某个点,使得无向图连通分支数最大,输出这个最大数. 有三种情况: 1.无向图无边时,最大数=点数-1: 2.无向图有边并不存在割点时,最大数=原图连通分支数-1 3.无向图 ...

  2. 洛谷 P3388 【模板】割点(割顶) 根+非根+dfn[]+low[]+不一样的Tarjan算法

    洛谷  P3388 [模板]割点(割顶)  根+非根+dfn[]+low[]+不一样的Tarjan算法 Tarjan算法,详见https://blog.csdn.net/mrcrack/article ...

  3. Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...

    转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...

  4. tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)

    基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...

  5. 海亮DAY8 关于Tarjan算法用于割点割边相关感受

    Tarjan 简介 Tarjan算法在求割点,割边,连通分量方面及其高效,在军事,交通,设计等方面有重要作用. 由于Tarjan算法思想并不难懂,在此不放上Tarjan算法的具体介绍. [Usaco2 ...

  6. 超详细Tarjan算法总结,求强连通分量,割点,割边,有重边的割边

    Tarjan是一个人,他一身中发明了很多算法,就这几个算法最为出名. 1.求有向图的强连通分量,那么什么是强连通分量呢,就是一个顶点集合,任意两个顶点间都可以互相到达.一个顶点也是强联通分量如果图中任 ...

  7. tarjan算法 割点割边强联通 算法讲解模板 自用整理

    很早就学过tarjan算法(割点割边与强联通)了,但是因为久不用老是忘,也有收藏过几篇不错的博客,但是每次需要时都要翻出那几篇太麻烦了,所以自己开篇记录方便自己的复习.图片和部分文字来源自其他博客,文 ...

  8. tarjan算法 (割点和桥)

    最近刚学习了tarjan算法,发一篇博客写一下自己的心得和理解. 在了解割点和桥之前,我们先理解什么是双连通. 双连通和强连通分别是应用于无向图和有向图中的,那么在学习双连通之前,请自行学习求强连通分 ...

  9. tarjan算法求无向图的割点和桥

    tarjan算法求无向图的割点与桥 一篇tarjan算法求割点与桥的完整的解释,写的真的好认真 以下代码来自kuangbin的模板 4.5 图的割点.桥和双连通分支的基本概念 [点连通度与边连通度] ...

  10. 20 求图的割点和割边—Tarjan算法

    1 图的割点 问题描述 去掉2号城市,这样剩下的城市之间就不能两两相互到达.例如4号城市不能到5号城市,6号城市也不能到达1号城市等等. 下面将问题抽象化.在一个无向连通图中,如果删除某个顶点后,图不 ...

最新文章

  1. Mysqldump参数大全
  2. CoTNet-重磅开源!京东AI Research提出新的主干网络CoTNet,在CVPR上获得开放域图像识别竞赛冠军
  3. asp.net mvc5编程实战_深圳荷坳车铣复合编程培训cnc数控编程技术
  4. Cpp 11 / override 和 final 区别
  5. 来不及想标题了,我要去打包收藏了 | 本周值得读
  6. 利用RMAN转移裸设备到文件系统
  7. 字符串匹配——枚举法
  8. ES6 变量的6种方式
  9. 分而治之:Oracle 18c 及 12.2 分区新特性的 N 种优化实践(含PPT)
  10. 百万数据查询优化技巧三十则
  11. 聊聊eureka的preferSameZoneEureka参数
  12. 深挖AI价值与温度,AETA地震预测AI算法大赛开启
  13. 【Java】SpringBoot后端格式转换:把PPT转成PDF
  14. 计算机-磁盘管理不能删除,关于win10系统磁盘管理磁盘右键菜单中只有“帮助”删除方法...
  15. 2021-08-25 Android studio 编译提示Version 28 (intended for Android Pie and below) is the last version of
  16. html表格图片垂直居中 css,利用Display: table;实现img图片垂直居中
  17. 少儿编程scratch如何快速上手?
  18. 软件测试中文电子版姚静_软件测试[(美)ron patton]读书笔记
  19. MySQL六十六问——面试复习必备
  20. 使用原生开发高仿瑞幸小程序(一):使用 Vant 组件库和配置多页面

热门文章

  1. mobileterminal命令大全
  2. 攻防世界 crypto Railfence
  3. Hive采集数据框架flume
  4. VC 2015 x86的DLL绿色包(QT 5.6)
  5. uniapp实现头像上传
  6. linux 批量修改文件后缀名
  7. linux批量修改文件后缀
  8. Oracle 建表语句,表结构操作sql
  9. 2021年7月国产数据库大事记
  10. ubuntu 安装openproj-1.4-2.noarch.rpm