tarjan

BZOJ 2707: [SDOI2012]走迷宫( tarjan + 高斯消元 )

本小妞迷上赌 提交于 2020-02-28 09:09:33
数据范围太大不能直接高斯消元, tarjan缩点然后按拓扑逆序对每个强连通分量高斯消元就可以了. E(u) = 1 + Σ E(v) / degree(u) 对拍时发现网上2个程序的INF判断和我不一样(他们2个的INF判断也不一样).....然而都A掉了....我觉得应该是他们写错了,我的做法应该没错的(正反2遍dfs,GDOI2015day1t1大冒险)(求打脸 ------------------------------------------------------------------------ #include<cmath> #include<stack> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 10009; const int maxb = 209; const double eps = 1e-8; int N, S, T, deg[maxn]; int dfn[maxn], low[maxn], sz[maxn], CK; int scc[maxn], Scc[maxn][maxb], Id[maxn], n; bool F[maxn]; stack<int> stk; double ans[maxn], mat

最近公共祖先(LCA)---tarjan算法

余生长醉 提交于 2020-02-24 23:17:52
LCA(最近公共祖先).....可惜我只会用tarjan去做 真心感觉tarjan算法要比倍增算法要好理解的多,可能是我脑子笨吧略略略 最近公共祖先概念 : 在一棵无环的树上寻找两个点在这棵树上深度最大的公共的祖先节点,也就是离这两个点最近的祖先节点。 最近公共祖先的应用:求解两个有且仅有一条确定的最短路径的路径     举个例子吧,如下图所示 4 和 5 的 最近公共祖先是2 , 5 和 3 的 最近公共祖先 是 1 , 2 和 1 的 最近公共祖先 是 1 。      这就是最近公共祖先的基本概念了,那么我们该如何去求这个最近公共祖先呢? Tarjan介绍:   通常初学者都会想到最简单粗暴的一个办法:对于每个询问,遍历所有的点,时间复杂度为 O(n*q), 那么这个复杂度当然也就呵呵了。     so, 我们有求解LCA的特殊算法:Tarjan /DFS+ST/倍增 (因为我不会,所以不喜欢)     后两个算法都是在线算法,也很相似,时间复杂度在 O(logn)~O(nlogn) 之间,我个人认为较难理解。     有的题目是可以用线段树来做的,但是其代码量很大,时间复杂度也偏高,在 O(n)~O(nlogn) 之间,优点在于也是 简单粗暴 。 tarjan属于离线算法,所谓的离线算法就是说我们需要将所有的询问都读入后一次性输出

LCA最近公共祖先(Tarjan离线算法)详解(转)

只谈情不闲聊 提交于 2020-02-21 04:55:15
转自 https://www.cnblogs.com/ECJTUACM-873284962/p/6613379.html 首先是最近公共祖先的概念(什么是最近公共祖先?):     在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上 深度最大 的 公共 的 祖先节点 。     换句话说,就是两个点在这棵树上 距离最近的公共祖先节点 。     所以LCA主要是用来处理当两个点仅有 唯一一条 确定的最短路径时的路径。     有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢?     答案是肯定的,很简单,按照人的亲戚观念来说, 你的父亲也是你的祖先 ,而LCA还可以 将自己视为祖先节点 。     举个例子吧,如下图所示 4 和 5 的 最近公共祖先是2 , 5 和 3 的 最近公共祖先 是 1 , 2 和 1 的 最近公共祖先 是 1 。      这就是最近公共祖先的基本概念了,那么我们该如何去求这个最近公共祖先呢?     通常初学者都会想到最简单粗暴的一个办法:对于每个询问,遍历所有的点,时间复杂度为 O(n*q) ,很明显, n和q一般不会很小 。     常用的求LCA的算法有:Tarjan/DFS+ST/倍增     后两个算法都是在线算法,也很相似,时间复杂度在 O(logn)~O(nlogn) 之间

强连通分量SCC(Tarjan)

折月煮酒 提交于 2020-02-12 16:14:11
什么叫强连通分量呢~ 有向图强连通分量在有向图G中, 如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。 如果有向图G的每两个顶点都强连通,称G是一个强连通图。 有向图的极大强连通子图,称为强连通分量(strongly connected components)。 举个例子: 一般来讲,我们选择的都是常数较小的线性算法: Tarjan 实际上,学习过无向图的割点之后, SCC的tarjan算法更好理解 tarjan ta老人家也是用dfs解决这个问题的 考虑强连通分量C,设其阿红第一个被发现的点为x, 则C中的其他点都是x的后代 我们希望在x访问完成时立即输出C,现在问题的关键就是判断一个点是否是SCC中第一个被发现的点 如图是一棵dfs树 虚线表示一条或多条边 假设我们正在判断u是不是SCC中的第一个点, 如果我们发现从u的子节点出发可以到达u的祖先w,显然u,v,w在一个SCC中 因此u不是第一个发现的结点 如果我们发现从v出发最多只能到达u,那么u就是SCC中第一发现的结点 注意 这里的 到达 ,只能通过当前SCC中的点,而不能通过已经确定的SCC中的点 很像无向图割点的low数组 所以我们也可以用类似的方法维护出某一点能够到达的最早祖先 附上一张图 vector

强连通分量SCC(Tarjan)

女生的网名这么多〃 提交于 2020-02-12 16:10:02
什么叫强连通分量呢~ 有向图强连通分量在有向图G中, 如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。 如果有向图G的每两个顶点都强连通,称G是一个强连通图。 有向图的极大强连通子图,称为强连通分量(strongly connected components)。 举个例子: 一般来讲,我们选择的都是常数较小的线性算法: Tarjan 实际上,学习过无向图的割点之后, SCC的tarjan算法更好理解 tarjan ta老人家也是用dfs解决这个问题的 考虑强连通分量C,设其阿红第一个被发现的点为x, 则C中的其他点都是x的后代 我们希望在x访问完成时立即输出C,现在问题的关键就是判断一个点是否是SCC中第一个被发现的点 如图是一棵dfs树 虚线表示一条或多条边 假设我们正在判断u是不是SCC中的第一个点, 如果我们发现从u的子节点出发可以到达u的祖先w,显然u,v,w在一个SCC中 因此u不是第一个发现的结点 如果我们发现从v出发最多只能到达u,那么u就是SCC中第一发现的结点 注意 这里的 到达 ,只能通过当前SCC中的点,而不能通过已经确定的SCC中的点 很像无向图割点的low数组 所以我们也可以用类似的方法维护出某一点能够到达的最早祖先 附上一张图 vector

TARJAN 算法求强连通分量

北慕城南 提交于 2020-02-12 15:55:54
在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。非强连通图有向图的极大强连通子图,称为强连通分量(strongly connected components)。 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达。{5},{6}也分别是两个强连通分量。 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。 定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。由定义可以得出, Low(u)=Min{DFN(u),Low(v),(u,v)为树枝边,u为v的父节点{ 如果下一个要访问的V节点,没有访问过,则low[U]=min(low[u],low[v])。 DFN(v),(u,v)为指向栈中节点的后向边(非横叉边)} {如果已经在栈中了,则low[U]=min(low[u],dfn[v]) 当 DFN(u)=Low(u) 时,以u为根的搜索子树上所有节点是一个强连通分量。 依照上面红色字体的定义,只要当DFN[U]=LOW[U] 便说明此时栈中的元素

有向图强连通分量的Tarjan算法——转自BYVoid

牧云@^-^@ 提交于 2020-02-12 13:01:09
[有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点 强连通 (strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个 强连通图 。非强连通图有向图的极大强连通子图,称为 强连通分量 (strongly connected components)。 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达。{5},{6}也分别是两个强连通分量。 直接根据定义,用双向遍历取交集的方法求强连通分量,时间复杂度为O(N^2+M)。更好的方法是Kosaraju算法或Tarjan算法,两者的时间复杂度都是O(N+M)。本文介绍的是Tarjan算法。 [Tarjan算法] Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。 定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为u或u的子树能够追溯到的最早的栈中节点的次序号。由定义可以得出, Low(u)=Min { DFN(u), Low(v),(u,v)为树枝边,u为v的父节点 DFN(v),(u,v)为指向栈中节点的后向边(非横叉边) } 当DFN(u)=Low(u)时,以u为根的搜索子树上所有节点是一个强连通分量。

Tarjan算法【强连通分量】

安稳与你 提交于 2020-02-12 12:29:16
转自: byvoid:有向图强连通分量的Tarjan算法 Tarjan算法是基于对图 深度优先搜索 的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中 未处理 的节点 加入一个 堆栈 , 回溯时 可以判断 栈顶到栈中的所有节点 是否为一个强连通分量。 有两个概念:1.时间戳,2.追溯值 时间戳是dfs遍历节点的次序。 定义DFN(u)为节点u搜索的次序编号(时间戳),Low(u)为 u或u的子树 能够追溯到的 栈中节点最小的次序号 。由定义可以得出: 1 Low(u)=min{ 2 DFN(u), // 自己的次序号 3 Low(v), //(u,v)为树枝边,u为v的父节点 4 DFN(v), //(u,v)为指向栈中节点的后向边(非横叉边) 5 } 即以下节点的最小值: 1. 自己、子树节点的次序号 2. 指向栈中节点(后向边节点)的次序号[等价于 DFN(v)<DFN(u)且v不为u的父亲节点],这里不是横叉边(指向不在栈中的节点)。 当 DFN(u)=Low(u) 时,以u为根的搜索子树上所有节点是一个强连通分量。 伪码: 1 tarjan(u) 2 { 3 DFN[u]=Low[u]=++Index // 为节点u设定次序编号和Low初值 4 Stack.push(u) // 将节点u压入栈中 5 for each (u, v) in E //

tarjan求强连通分量

雨燕双飞 提交于 2020-02-12 12:28:54
转载自 http://www.cnblogs.com/shadowland/p/5872257.html 一.算法简介 我们定义: 如果两个顶点可以 相互通达 ,则称两个顶点 强连通 (strongly connected)。如果有向图G的 每两个顶点都强连通 ,称G是一个 强连通图 。有向图的 极大强连通子图 ,称为 强连通分量 (strongly connected components)。 例如:在上图中,{1 , 2 , 3 , 4 } , { 5 } , { 6 } 三个区域可以相互连通,称为这个图的强连通分量。 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。 再Tarjan算法中,有如下定义。 DFN[ i ] : 在DFS中该节点被搜索的次序(时间戳) LOW[ i ] : 为i或i的子树能够追溯到的 最早的栈中节点 的次序号 当DFN[ i ]==LOW[ i ]时,为i或i的子树可以构成一个强连通分量。 二.算法图示 以1为Tarjan 算法的起始点,如图 顺次DFS搜到节点6 回溯时发现LOW[ 5 ]==DFN[ 5 ] , LOW[ 6 ]==DFN[ 6 ] ,则{ 5 } , { 6 } 为两个强连通分量。回溯至3节点