tarjan

【JZOJ2758】【SDOI2012】走迷宫(labyrinth)

旧巷老猫 提交于 2020-01-30 04:09:16
╰( ̄▽ ̄)╭ Morenan 被困在了一个迷宫里。 迷宫可以视为 N 个点 M 条边的有向图,其中 Morena n处于起点 S , 迷宫的终点设为 T 。 可惜的是 , Morenan 非常的脑小 , 他只会从一个点出发随机沿着一条从该点出发的有向边 , 到达另一个点 。 这样 , Morenan 走的步数可能很长 , 也可能是无限,更可能到不了终点。 若到不了终点,则步数视为无穷大。 但你必须想方设法求出 Morenan 所走步数的期望值。 (⊙ ▽ ⊙) 一开始看着道题,就觉得是tarjan缩点后,转化成DAG上的问题。 当原图是DAG时 设 f i 表示第 i 个点走到终点的距离。 容易有 f i = ∑ j ∈ n e x t ( i ) 1 | n e x t ( i ) | ∗ ( f j + 1 ) , 其中 n e x t ( i ) 是 i 的后继集合。 很容易使用拓扑排序来完成动态规划。 当原图是一般的有向图时 利用 t a r j a n 算法可以把图中的强连通分量找出来。 对于任意一个强连通分量,我们利用高斯消元来求解出强连通分量中的每个点的 f 值。 套上拓扑排序,就能够解决。 时间复杂度为 O ( n ∗ L 3 ) ,其中 L 为最大强连通分量的大小。 实际时间复杂度则远远不到。 ( ̄~ ̄) 高斯(gauss)消元: 1.目标 对 n 条 n

Tarjan & LCA 套题题目题解

拟墨画扇 提交于 2020-01-29 17:21:42
刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <set> #include <list> #include <cmath> #include <ctime> #include <deque> #include <stack> #include <queue> #include <cctype> #include <cstdio> #include <string> #include <vector> #include <climits> #include <cstdlib> #include <cstring> #include <iostream> #include <algorithm> #define LL long long #define PI 3.1415926535897932626 using namespace std; int gcd(int a, int b) {return a % b == 0 ? b : gcd(b, a % b);} const int MAXN = 40040; const int MAXM = MAXN * 2; const int INF = 0x3f3f3f3f; struct Edge { int

LCA:Tarjan算法实现

北慕城南 提交于 2020-01-29 03:41:54
本博文转自http://www.cnblogs.com/JVxie/p/4854719.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) 之间

双连通分量

╄→尐↘猪︶ㄣ 提交于 2020-01-26 18:26:44
目录 双连通分量 前置知识 基本概念 点双连通分量 代码 边双连通分量 代码 例题 P3225 矿场搭建 hdu4612 Warm up 双连通分量 前置知识 @FISHER_ —— 强连通分量 @szTom —— 割点和桥 不抄代码的好习惯 基本概念 双连通分量又分点双连通分量和边双连通分量两种。若一个无向图中的去掉任意一个节点(一条边)都不会改变此图的连通性,即不存在割点(桥),则称作点(边)双连通图。一个无向图中的每一个极大点(边)双连通子图称作此无向图的点(边)双连通分量。求双连通分量可用Tarjan算法。——百度 简单来说,一个没有割点(桥)的无向图就是点(边)双连通分量。 以下图为例: 对于这个图来说一共有2个点双连通分量,分别是: (1,2,5),(2,3,4) 有3个边双连通分量,分别是: (1,2,5),(2,3,4),(1,2,3,4,5) 点双连通分量 首先对于一个点双连通分量来说,里面一定没有割点。 所以说当我们查找到一个割点u的时候,就将以u为根的搜索子树内 还不属于任何一个点双连通分量 且 不为割点 或 为割点 但 与那些以u为根的搜索子树内 还不属于任何一个点双连通分量 且 不为割点 的点 直接连通的点 为一个点双连通分量。 简单来说,就是当我们查找到一个割点的时候,我们像 强连通分量 那样让仍在栈内的点成为一个点双连通分量。 最后附上代码: 代码

Tarjan算法专练

左心房为你撑大大i 提交于 2020-01-24 16:46:32
1. 迷宫城堡 题意:给一个图判断是否是强连通图。 题解:利用Tarjan计算图中强连通分量的个数,如果为1则是强连通图,否则不是。 #include<bits/stdc++.h> using namespace std; const int N = 2e4+100; typedef long long ll; vector<int> G[N]; bool is_instack[N]; int dfn[N],low[N]; stack<int> sta; int n,m,index,scc; void init(){ index=scc=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); memset(is_instack,0,sizeof(is_instack)); while(!sta.empty()) sta.pop(); for(int i=1;i<=n;i++) G[i].clear(); } void Tarjan(int u){ dfn[u]=low[u]=++index; sta.push(u);is_instack[u]=1; for(auto v:G[u]){ if(!dfn[v]){ Tarjan(v); low[u]=min(low[u],low[v]); } else if(is_instack

Tarjan算法求LCA

走远了吗. 提交于 2020-01-19 16:01:14
题源: https://loj.ac/problem/10130 这个题还是debug了好久。。 1.调用函数中如果要更改外部数据需要传递引用,其实传递引用往往效率更高,以后要多加注意这一点。 2.忘写并查集了 (捂脸逃) 3.题目要求的是距离而不是lca,认真审题。。 贴代码: #include <iostream> #include <stdio.h> #include <cstring> #define maxn 100005 //#define LOCAL using namespace std; struct Edge { int next, to, dis; } edge[maxn * 2], queryEdge[maxn * 2]; //两倍存储(不知道父子关系与遍历的先后顺序) int head[maxn], queryHead[maxn], e1 = -1, e2 = -1, fa[maxn], vs[maxn], dep[maxn]; //dep用来记录深度求距离 void addedge(int *head, Edge *edge, int &e, int x, int y) //e要传递引用来进行更改,否则++无效 { edge[++e].next = head[x], edge[e].to = y, head[x] = e; edge[++e].next

一本通tarjan题目

无人久伴 提交于 2020-01-12 08:52:31
目录 loj 10091 受欢迎的牛 10093 网络协议 10094 消息的传递 10095 间谍网络 10096 抢掠计划 基本上都是板子, 还没做完 loj 10091 受欢迎的牛 缩点后出度为$ 0 $的点就是欢迎的牛,超过一个点则不存在 #include <bits/stdc++.h> using namespace std; const int N = 10000 + 50; const int M = 50000 + 50; struct node { int next, to; } edge[M]; int cnt, head[N]; inline void add(int from, int to) { edge[++cnt] = (node){ head[from], to }, head[from] = cnt; } int n, m, col, top, tot; int cd[N], color[N], Stack[N], low[N], dfn[N], visited[N], sum[N]; // namespace newgraph{ // int cnt, head[N]; // struct node{ int next, to; }edge[M]; // inline void add(int from, int to) { edge[++cnt

tarjan缩点+dag上dp

旧时模样 提交于 2020-01-06 22:05:30
题目描述 给定一个 n个点 mm条边有向图,每个点有一个权值,求一条路径,使路径经过的点权值之和最大。你只需要求出这个权值和。 允许多次经过一条边或者一个点,但是,重复经过的点,权值只计算一次。 输入格式 第一行两个正整数 n,m 第二行 n个整数,依次代表点权 第三至 m+2 行,每行两个整数 u,v,表示一条 u→v 的有向边。 输出格式 共一行,最大的点权之和。 输入输出样例 输入 #1 2 2 1 1 1 2 2 1 输出 #1 2 #include < cstdio > #include < cstring > #include < algorithm > #include < cmath > using namespace std ; const int maxn = 100005 ; int n , m ; int head [ maxn ] , tot ; int dfn [ maxn ] , low [ maxn ] , Stack [ maxn ] , sum [ maxn ] , belong [ maxn ] , top , ans , cnt ; int x [ maxn ] , y [ maxn ] , w [ maxn ] , dis [ maxn ] ; bool vis [ maxn ] ; struct node { int to , next

HDU 4587 B - TWO NODES tarjan

…衆ロ難τιáo~ 提交于 2020-01-05 03:19:31
B - TWO NODES Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=87326#problem/B Description Suppose that G is an undirected graph, and the value of stab is defined as follows: Among the expression,G -i, -j is the remainder after removing node i, node j and all edges that are directly relevant to the previous two nodes. cntCompent is the number of connected components of X independently. Thus, given a certain undirected graph G, you are supposed to calculating the value of stab . Input The input will contain the description of several graphs. For

Tarjan算法

馋奶兔 提交于 2019-12-21 11:38:55
Tarjan算法整理 ( [转自: http://blog.sina.com.cn/s/blog_60707c0f0100xdh5.html ][ http://blog.sina.com.cn/s/blog_71aa4dbb01010qsc.html ] [ http://blog.sina.com.cn/s/blog_71aa4dbb01010pq0.html ] ) 基本概念 : 1. 割点: 若删掉某点后,原连通图分裂为多个子图,则称该点为 割点 。 2. 割点集合 :在一个无向连通图中,如果有一个顶点集合,删除这个顶点集合,以及这个集合中所有顶点相关联的边以后,原图变成多个连通块,就称这个点集为 割点集合 。 3. 点连通度 :最小割点集合中的顶点数。 4. 割边 ( 桥 ) :删掉它之后,图必然会分裂为两个或两个以上的子图。 5. 割边集合 :如果有一个边集合,删除这个边集合以后,原图变成多个连通块,就称这个点集为 割边集合 。 6. 边连通度 :一个图的 边连通度 的定义为,最小割边集合中的边数。 7. 缩点 :把没有割边的连通子图缩为一个点,此时满足任意两点之间都有两条路径可达。 注:求块 <> 求缩点。缩点后变成一棵 k 个点 k-1 条割边连接成的树。而割点可以存在于多个块中。 8. 双连通分量 : 分为点双连通和边双连通 。 它的标准定义为