图论复习之强连通分量以及缩点—Tarjan算法
在一个图的子图中,任意两个点相互可达,也就是存在互通的路径,那么这个子图就是强连通分量。(如果一个有向图的任意两个点相互可达,那么这个图就称为强连通图)。
【性质】
如果u是某个强连通分量的根,那么:
(1)u不存在路径可以返回到它的祖先。
(2)u的子树也不存在路径可以返回到u的祖先。
【算法描述】
(1)我们先对每一个顶点判断,如果已经被运行过了,则不动,否则进行拓展
(2)对于每一个点,我们设2个值来表示(dfn和low){low[i]表示结点i的根结点的dfn值},dfn则是结点i的时间戳
(3)在第一次顺序遍历时,dfn[u]=low[u]=++cnt,初始化序列
(4)然后将遍历到的点压入栈,并且置为已做过
(5)在整个图中枚举一条以u为右端点的边(from,to),然后判断左端点是否已经入栈,如果已经入栈,则修改low[u]:low[u]=max(low[u],dfn(to)),如果没入栈,则对其进行递归处理,返回时low[u]=min(low[u],low[to])
(6)当出现dfn[u]==low[u]时,则表明已经出现一个强联通分量,依次弹出并消除标记即可,此时cnt++,则该作用为统计联通块数量
【总结】
上述算法时间复杂度O(N+M)
【例题】
codevs2822《爱在心中》
“每个人都拥有一个梦,即使彼此不相同,能够与你分享,无论失败成功都会感动。爱因为在心中,平凡而不平庸,世界就像迷宫,却又让我们此刻相逢Our Home。”
在爱的国度里有N个人,在他们的心中都有着一个爱的名单,上面记载着他所爱的人(不会出现自爱的情况)。爱是具有传递性的,即如果A爱B,B爱C,则A也爱C。
如果有这样一部分人,他们彼此都相爱,则他们就超越了一切的限制,用集体的爱化身成为一个爱心天使。
现在,我们想知道在这个爱的国度里会出现多少爱心天使。而且,如果某个爱心天使被其他所有人或爱心天使所爱则请输出这个爱心天使是由哪些人构成的,否则输出-1。
第1行,两个数N、M,代表爱的国度里有N个人,爱的关系有M条。
第2到第M+1行,每行两个数A、B,代表A爱B。
第1行,一个数,代表爱的国度里有多少爱心天使。
第2行,如果某个爱心天使被其他所有人和爱心天使所爱则请输出这个爱心天使是由哪些人构成的(从小到大排序),否则输出-1。
样例输入1:
6 7
1 2
2 3
3 2
4 2
4 5
5 6
6 4
样例输入2:
3 3
1 2
2 1
2 3
样例输出1:
2
2 3
样例输出2:
1
-1
很明显,对于题目的第一问,我们只需要将给出的关系图跑一遍裸的tarjan即可
然而第二问显然就不是那么简单了,题目要求我们找出容量为n-1的联通块,这里要注意:
不能直接计算,因为你的图已经被第一问毁了。所以要再次构图
然后统计每个点的“爸爸”以及每个点的强联通分量个数
再寻找为n的即可,然后依次输出
时间复杂度O(4N+M)
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;const int MaxN=1001;int s[MaxN],top;
int n,m;
int ans;//联通块个数
int dfn[MaxN],low[MaxN];
bool vis[MaxN],inq[MaxN];
int belong[MaxN];
int head[MaxN],hav[MaxN],h[MaxN];struct graph{int to,next;
}G[MaxN],R[MaxN];int cnt1=0,cnt2=0;inline int minx(int a,int b){return a<b?a:b;}void addedge(int u,int v){G[++cnt1].to=v;G[cnt1].next=head[u];head[u]=cnt1;
}void tarjan(int u){dfn[u]=low[u]=++cnt2;s[++top]=u;vis[u]=inq[u]=true;for(int i=head[u];i!=0;i=G[i].next){if(!dfn[G[i].to]){tarjan(G[i].to);low[u]=minx(low[u],low[G[i].to]);}else if(inq[G[i].to])low[u]=minx(low[u],dfn[G[i].to]);}if(dfn[u]==low[u]){ans++;int j=0;while(j!=u){j=s[top--];inq[j]=false;belong[j]=ans;++hav[ans];}}
}void rebuild(){int i,j,cnt=0;for(i=1;i<=n;i++)for(j=head[i];j!=0;j=G[j].next)if(belong[G[j].to]!=belong[i]){R[++cnt].to=belong[G[j].to];R[cnt].next=h[belong[i]];h[belong[i]]=cnt;}
}
void work(){int i,ans1=0;for(i=1;i<=n;i++){if(!vis[i])tarjan(i);}rebuild();for(i=1;i<=ans;i++)if(hav[i]>1)ans1++;printf("%d\n",ans1);ans1=-1;for(i=1;i<=ans;i++)if(!h[i]){if(ans1!=-1 || hav[i]==1){ans1=-1;break;}elseans1=i;}if(ans1==-1)printf("%d",ans1);else {for(i=1;i<=n;i++)if(belong[i]==ans1)printf("%d ",i);}
}int main(){scanf("%d %d",&n,&m);int i,u,v;memset(vis,false,sizeof(vis)); for(i=1;i<=m;i++){scanf("%d %d",&u,&v);addedge(u,v);}work();return 0;
}
-----------------------------------------thanks for watching------------------------------------------
图论复习之强连通分量以及缩点—Tarjan算法相关推荐
- 强连通分量及缩点tarjan算法解析
http://blog.csdn.net/justlovetao/article/details/6673602 有向图强连通分量的Tarjan算法 [有向图强连通分量] 在有向图G中,如果两个顶点间 ...
- tarjan算法不是很懂先mark一下。
前面为转载的.后面是自己的理解. 三种tarjan算法(上) .这篇算是做一个总结吧. 求强连通分量 求无向图的割和桥 最近公共祖先 求强连通分量 基本概念: 强连通是有向图才有的概念. ...
- tarjan算法与无向图的连通性(割点,桥,双连通分量,缩点)
基本概念 给定无向连通图G = (V, E) 割点: 对于x∈V,从图中删去节点x以及所有与x关联的边之后,G分裂为两个或两个以上不相连的子图,则称x为割点 割边(桥) 若对于e∈E,从图中删去边e之 ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...
转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...
- 图论--SCC缩点--Tarjan
// Tarjan算法求有向图强连通分量并缩点 /*强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作.*/ #include< ...
- 图论--SCC强连通缩点--Tarjan
强连通缩点与双连通缩点大同小异,也就是说将强连通分支缩成一个点之后,没有强连通,成为有向无环图,在对图进行题目的操作. // Tarjan算法求有向图强连通分量并缩点 #include<iost ...
- 强连通分量(Tarjan算法)和缩点
强连通分量(Tarjan算法)和缩点 一些定义 给定一张有向图,对于图中任意两个节点 xxx 和 yyy ,存在从 xxx 到 yyy 的路径,也存在从 yyy 到 xxx 的路径,则称该有向图为强连 ...
- 0x66.图论 - Tarjan算法与无向图连通性
目录 一.无向图的割点与桥 割点 桥/割边 时间戳 搜索树 追溯值 二.割边判定法则 三.割点判定法则 1.luogu P3388 [模板]割点(割顶) 2.luogu P3469 [POI2008] ...
- 【转】BYV--有向图强连通分量的Tarjan算法
转自beyond the void 的博客: https://www.byvoid.com/zhs/blog/scc-tarjan 注:红色为标注部分 [有向图强连通分量] 在有向图G中,如果两个顶点 ...
最新文章
- mysql 视图列信息_MySQL 中获取用户表、用户视图、用户表中列信息
- Apache(4)——配置文件里的各参数(2)
- java 删除某一个学生_java编写一个程序,实现功能(定义一个类学生表示学生1. 增加学生2显示 3. 修改 4. 删除5查找某...
- Codeforces Round #723 (Div. 2) D. Kill Anton 线段树 + 暴力
- 解决BLOB/TEXT column can‘t have a default value query问题
- Excel文件处理实战-Python编程进阶
- NOIP2016D2T2 蚯蚓
- [一定要看完]住在隔壁的刚毕业的大学生小夫妻
- android歌词控件
- 萤火虫小程序_实测!成都人私藏的免费耍水地,抓螃蟹、烤烧烤、赏萤火虫,周末一天来回!...
- mysql8.0怎么设置中文版_MySQL 8.0 版本修改字符编码
- 手机便签怎么对待办分类文件夹加密
- oracle大表新增字段并赋值,oracle批量新增字段 数据赋值应用
- excel页码怎么设置从4开始?
- python的加减乘除运算_python四则运算
- 计算机音乐设备简单配置,计算机音乐与作曲基础(高等学校艺术类专业计算机规划教材)...
- 二叉查找树,二叉平衡树
- 计算机无法识别硬盘怎么办,硬盘电脑不识别怎么办?硬盘数据怎么恢复?
- linux上最好的p图软件,10款好用的手机P图软件排行榜
- MFC exe文件生成的图标更改方法
热门文章
- 在家无聊?16篇最新推荐系统论文送你
- Building a Restful Web Service(最好的Spring入门教程 --来自Spring官网的Guides)
- 多彩绚丽渐变Mac动态壁纸
- 网页背景动态线条 鼠标吸附动态线条效果的实现
- Unity打开VS,一直显示hold on,一直在加载资源的解决办法
- c语言桶是什么意思,桶排序算法
- autoscraper网络刮板模块总结
- BufferQueue has been abandoned解决方案
- node.js基于微信小程序的校园失物招领毕业设计源码072343
- 2021-07-12 JDK、KRE、JVM