连通分量

强连通分量

限于喜欢 提交于 2019-11-29 14:20:15
tarjan 基于深度优先搜索,用于寻找有向图中的连通块。 主要代码如下: inline void tarjan(int x){ dfn[x]=low[x]=++idx; vis[x]=1; sta[++top]=x; for(int i=head[x];i;i=e[i].nxt){ int v=e[i].v; if(!dfn[v]){//还未访问过这个节点 tarjan(v); low[x]=min(low[x],low[v]); } else if(vis[v]==1){//这个节点在栈中 low[x]=min(low[x],dfn[v]); } } if(dfn[x]==low[x]){//找到一个强联通分量 ++cnt; while(x!=sta[top]){ vis[sta[top]]=0; qlt[sta[top]]=cnt;//染色,标记这个节点属于第几号强联通分量 siz[cnt]++;//记录这一个连通块的节点数 top--; } vis[x]=0;//还要将这个节点弹出来 qlt[x]=cnt; siz[cnt]++; top--; } } 如果是要遍历整张图找到所有的连通块,通常还要加这句 for(int i=1;i<=n;i++){ if(!dfn[i]) tarjan(i); } 因为图中不一定全部都是联通的。 每一个点只访问了一次

tarjan算法——边双连通分量

倖福魔咒の 提交于 2019-11-29 09:49:38
简介: 还是采用tarjan缩点,如果边(u,v)是桥,那么显然dfn[v]=low[v],则v此时栈中的集合为一个边连通分量。 代码: 1 void tarjan(int x,int &sccnum,int from) { 2 sta[++cnt]=x; 3 vis[x]=1; 4 dfn[x]=++lay; 5 low[x]=lay; 6 bool flag=false; 7 for(int i=head[x];~i;i=e[i].net) { 8 int v=e[i].v; 9 if(v==from&&!flag) { ///如果是重边的情况 10 flag=true; 11 continue; 12 } 13 if(!dfn[v]) { 14 tarjan(v,sccnum,x); 15 low[x]=min(low[x],low[v]); 16 } 17 else if(vis[v]==1) 18 low[x]=min(low[x],low[v]); 19 } 20 if(dfn[x]==low[x]) { ///有割边 21 ++sccnum; 22 do { 23 f[sta[cnt]]=sccnum; ///标记为同一集合 24 vis[sta[cnt]]=2; 25 }while(sta[cnt--]!=x); 26 } 27 } View Code 来源:

图的割点、桥与双连通分支

可紊 提交于 2019-11-28 06:44:52
先来%一下Robert Tarjan前辈 %%%%%%%%%%%%%%%%%% 然后是热情感谢下列并不止这些大佬的博客: 图连通性(一):Tarjan算法求解有向图强连通分量 图连通性(二):Tarjan算法求解割点/桥/双连通分量/LCA 初探tarjan算法(求强连通分量) 关于Tarjan算法求点双连通分量 图的割点、桥与双连通分支 感谢有各位大佬的博客帮助我理解和学习,接下来就是进入正题。 关于tarjan,之前我写过一个是求lca的随笔,而找lca只是它一个小小的功能,它还有很多其他功能,具体是什么,我就根据自己的学习进程,一步步来自我回忆一下。 第一个是有向图求强连通分量。 让我们来引进百度 有向图强连通分量:在 有向图 G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点 强连通 (strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个 强连通图 。有向图的极大强连通子图,称为强连通 分量 (strongly connected components)。 通俗解释,强连通就是有向图中,任意两个顶点彼此有一条路可以可以走到,而强连通分量就是它的强连通子图,极大强连通分量就是它最大的那个强连通子图。 而详细步骤的话,上面的博客已经讲得很清楚了,我就简单的阐述一下步骤。

【还是畅通工程 HDU - 1233】【Kruskal模板题】

跟風遠走 提交于 2019-11-28 06:28:15
Kruskal算法讲解 该部分内容全部摘录自刘汝佳的《算法竞赛入门经典》 Kruskal算法的第一步是给所有边按照从小到大的顺序排列。 这一步可以直接使用库函数 qsort或者sort。 接下来从小到大依次考查每条边(u,v)。 情况1: u和v在同一个连通分量中, 那么加入(u, v)后会形成环, 因此不能选择。 情况2: 如果u和v在不同的连通分量, 那么加入(u, v)一定是最优的。 为什么呢? 下面用 反证法——如果不加这条边能得到一个最优解T, 则T+(u, v)一定有且只有一个环, 而且环中 至少有一条边(u' , v')的权值大于或等于(u,v)的权值。 删除该边后, 得到的新树T'=T+(u, v)-(u', v')不会比T更差。 因此, 加入(u, v)不会比不加入差。 下面是伪代码: 把所有边排序, 记第i小的边为e[i]( 1<=i<m) 初始化MST为空 初始化连通分量, 让每个点自成一个独立的连通分量 for(int i = 0; i < m; i++) if(e[i].u和e[i].v不在同一个连通分量) { 把边e[i]加入MST 合并e[i].u和e[i].v所在的连通分量 } 在上面的伪代码中, 最关键的地方在于“连通分量的查询与合并”: 需要知道任意两个点 是否在同一个连通分量中, 还需要合并两个连通分量。这就用到了并查集

洛谷 - P3469 - BLO-Blockade - 割点

空扰寡人 提交于 2019-11-27 11:56:54
https://www.luogu.org/problem/P3469 翻译:一个原本连通的无向图,可以删除图中的一个点,求因为删除这个点所导致的不连通的有序点对的数量。或者说,删去这个点之后,各个连通分量的大小的乘积之和? 当然是考虑新学的Tarjan法求割点。一遍Tarjan给每个点记录他是不是割点。然后第二遍的时候对每个割点,统一它连接的 来源: https://www.cnblogs.com/Yinku/p/11361600.html

模板 - 边双连通分量

断了今生、忘了曾经 提交于 2019-11-27 11:32:17
DFS 找桥并判断边双连通 首先,对原图进行 DFS。 如上图所示,黑色与绿色边为树边,红色边为非树边。每一条非树边连接的两个点都对应了树上的一条简单路径,我们说这条非树边 覆盖 了这条树上路径上所有的边。绿色的树边 至少 被一条非树边覆盖,黑色的树边不被 任何 非树边覆盖。 我们如何判断一条边是不是桥呢?显然,非树边和绿色的树边一定不是桥,黑色的树边一定是桥。 如何用算法去实现以上过程呢?首先有一个比较暴力的做法,对于每一条非树边,都逐个地将它覆盖的每一条树边置成绿色,这样的时间复杂度为 。 怎么优化呢?可以用差分。对于每一条非树边,在其树上深度较小的点处打上 -1 标记,在其树上深度较大的点处打上 +1 标记。然后 求出每个点的子树内部的标记之和。对于一个点u其子树内部的标记之和等于覆盖了u和u的父亲p之间的树边的非树边数量。若这个值非0,则u和u的父亲p之间的树边不是桥,否则是桥。 用以上的方法 求出每条边分别是否是桥后,两个点是边双连通的,当且仅当它们的树上路径中不包含桥。 意思是dfs然后顺带打上差分,再dfs顺带求出子树内部标记之和(dfs记录子树大小然后dfs序前缀和作差),把这个和标记在u节点上,那么除了根节点以外每个节点都指定一条树边。最后跑一次树剖验证路径和为0。 来源: https://www.cnblogs.com/Yinku/p/11361533.html

双连通分量和强连通分量的总结

故事扮演 提交于 2019-11-27 05:48:16
【双连通分量】 一、边双连通分量定义 在分量内的任意两个点总可以找到两条边不相同的路径互相到达。总而言之就是一个圈,正着走反着走都可以相互到达,至少只有一个点。 二、点双连通分量的定义 参照上面,唯一的不同:任意两个点可以找到一个点不同的路径互相到达。也是一个圈,正反走都可以,至少为一个点。 三、边、点双连通分量模板代码要注意的地方 边双连通分量: 1.每个节点的所有儿子遍历后才开始计算分量大小,请与点双连通相区分; 2.割顶只能属于一个分量,请与割边区分;(容易搞混) 3.要注意j是否是i的父节点; 点双连通分量: 1.每遍历一个儿子就计算是否有点连通分量; 2.割顶可以属于多个连通分量,请注意与割边区分; 3.当i为根节点时,至少要有两个儿子才能是割点; 【强连通分量】 一、定义 有向图上的环,不啰嗦,与上面两种类似,至少为一个点; 二、模板代码注意的地方 1.每个点所有儿子遍历完才开始求分量;(类似边双连通分量) 2.每个点只能属于一个分量; 【强连通分量和双连通分量常见的模型和问法】 双连通分量 1.给出的图是非连通图,如: a.有一些点,一些边,加最少的边,要使得整个图变成双联通图。 大致方法:求出所有分量,把每个分量看成一个点,统计每个点的度,有一个度为一则cnt加1,答案为(cnt+1)/2; b.有一些点,一些边,问最少多少个点单着。 大致方法:求出所有的分量即可

连通图和连通分量

可紊 提交于 2019-11-27 00:04:33
连通图和连通分量 1.顶点间的连通性   在无向图G中,若从顶点vi到顶点vj有路径(当然从vj到vi也一定有路径), 快看小说网 则称vi和vj是连通的。 2.连通图  若V(G)中任意两个不同的顶点vi和vj都连通(即有路径),则称G为连通图(Con-nected Graph)。 【例】图G2,和G3是连通图。 ​ 3.连通分量  无向图G的极大连通子图称为G的最强连通分量(Connected Component)。 注意:   ① 任何连通图的连通分量只有一个,即是其自身  ② 非连通的无向图有多个连通分量。 【例】下图中的G4是非连通图,它有两个连通分量H1和H2。 ​ 强连通图和强连通分量 1.强连通图   有向图G中,若对于V(G)中任意两个不同的顶点vi和vj, 情定三生:首席医少赖上门 都存在从vi到vj以及从vj到vi的路径,则称G是强连通图。 2.强连通分量  有向图的极大强连通子图称为G的强连通分量。 注意:  ① 强连通图只有一个强连通分量,即是其自身。  ② 非强连通的有向图有多个强连分量。 【例】下图中的G1不是强连通图,因为v3到v2没有路径,但它有两个强连通分量,如右图所示。 ​ 网络(Network)   若将图的每条边都赋上一个权,则称这种带权图为网络( 超级人生 )。 注意:   权是表示两个顶点之间的距离、耗费等具有某种意义的数。   【例

又是图论.jpg

…衆ロ難τιáo~ 提交于 2019-11-26 23:06:43
BZOJ 2200 道路和航线重讲ww: FJ 正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到 T 个城镇 (1 ≤ T ≤ 25000),编号为 1 到 T。这些城镇之间通过 R 条道路 (1 ≤ R ≤ 50000) 和 P 条航线(1 ≤ P ≤ 50000) 连接。每条道路 i 或者航线 i 连接城镇 Ai 到Bi,花费为 Ci。对于道路, 0 ≤ Ci ≤ 10000; 然而航线的花费很神奇,花费 Ci 可能是负数 (-10000 ≤ Ci ≤ 10000)。道路是双向的,可以从 Ai 到 Bi,也可以从 Bi 到 Ai,花费都是 Ci。然而航线与之不同,只可以从 Ai 到 Bi。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证: 如果有一条航线可以从 Ai 到 Bi,那么保证不可能通过一些道路和航线从 Bi 回到Ai。 (有向边不存在于任何一个环,环都是正权无向边)由于 FJ 的奶牛世界公认〸分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇 S 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。 (求从s出发到某个点的单源最短路);O(nlogn) 把所有无向边加进去,形成若干连通块,看成一个大的点,然后加入有向边,形成一个DAG,如果有连通块的入度为0,直接连通块内跑dijkstar:以已更新的dis为基础ww

HDU 3639 Hawk-and-Chicken (强连通缩点+DFS)

↘锁芯ラ 提交于 2019-11-26 21:26:06
< 题目链接 > 题目大意: 有一群孩子正在玩老鹰抓小鸡,由于想当老鹰的人不少,孩子们通过投票的方式产生,但是投票有这么一条规则:投票具有传递性,A支持B,B支持C,那么C获得2票(A.B共两票),输出最多能获得的票数是多少张和获得最多票数的人是谁?(如果有多个人获得的票数都是最多的,就将他们全部输出)。 解题分析: 不难看出,同一连通分量的所有点得到的票数肯定是相同的,所以我们先将原图进行Tarjan缩点。对于缩完点后的图,我们发现,票数最多的人一定在出度为0的"点"中,因为如果票数最多的点不是出度为0的"点",那么它所到达的那个"点"的票数一定大于当前"点"的票数,这与当前"点"票数最多相矛盾。然后考虑对入度为0的"点"的票数统计,我们可以在缩点后进行重新构图,相互连通的"点"之间建立反边(投票方向相反),这样方便DFS统计当前"点"的票数。需要注意的是,当前连通分量中所有的点在当前连通分量中获得的票数为num[now]-1(因为要除去自己),然后再加上以这个点为起点,能够到达所有连通分量的点数,即为这个点能够得到的票数。 来源: https://www.cnblogs.com/DWVictor/p/11333716.html