tarjan

LuoguP2002 消息扩散 tarjan求scc

强颜欢笑 提交于 2019-12-01 06:12:05
模板,注意有个地方打错好多次了: for(int j = 0;j < scc[i].size();j++)——是j++不是i++!!! 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<vector> 5 using namespace std; 6 7 const int Maxn = 100010; 8 9 int ind[Maxn],dfn[Maxn],low[Maxn],stack[Maxn],ins[Maxn],inscc[Maxn]; 10 vector<int> scc[Maxn],g[Maxn]; 11 int cntscc,cntv,n,m,top; 12 13 void tarjan(int x){ 14 dfn[x] = low[x] = ++cntv; 15 ins[x] = 1,stack[++top] = x; 16 for(int i = 0;i < g[x].size();i++){ 17 int u = g[x][i]; 18 if(!dfn[u])tarjan(u),low[x] = min(low[x],low[u]); 19 else if(ins[u])low[x] = min(low[x],dfn[u]); 20 } 21 if(dfn[x] ==

Tarjan求有向图强连通分量 BY:优少

烂漫一生 提交于 2019-12-01 05:02:02
Tarjan算法:一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法。 定义给出之后,让我们进入算法的学习。。。 【情境引入】 【 HAOI2006 受欢迎的牛】 题目描述: 每头奶牛都梦想成为牛棚里的明星。被所有奶牛喜欢的奶牛就是一头明星奶牛。所有奶 牛都是自恋狂,每头奶牛总是喜欢自己的。奶牛之间的“喜欢”是可以传递的——如果A喜 欢B,B喜欢C,那么A也喜欢C。牛栏里共有N 头奶牛,给定一些奶牛之间的爱慕关系,请你 算出有多少头奶牛可以当明星。 可以看出,当将每一个强连通分量视为每一个点时,受欢迎的奶牛只有可能是图中唯一的出度为零的点中的所有奶牛 这个时候,强连通分量的求得就出现了问题,这个时候,Tarjan算法应运而生 概念引入: 在有向图G中,如果两个顶点可以相互到达,则称两个顶点强连通。 如果有向图G的任意两个顶点都强连通,称G是一个强连通图。 非强连通有向图的极大强连通子图,称为强连通分量。 下图中,子图{1,2,3,4}为一个强连通分量,因为顶点1,2,3,4两两可达。{5},{6}也分别是两个强连通分量。 算法实现: Tarjan算法是基于对图深度优先搜索的算法。搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断栈顶到栈中的节点是否为一个强连通分量。 相比看完这个莫名其妙的东西很少有人能理解,那就让我们进入具体讲解: 算法准备:

机房测试11:信息拦截 (tarjan缩点+正反拓扑)

三世轮回 提交于 2019-12-01 04:58:43
题目: 分析: 这道题真的毒瘤,思想很简单,但是细节很多。。 题意: 找到从1~n的必经点(每条信息都能获取),且不在一个点数>=2 的强连通分量中(恰好获取一次)。 先将有向图缩点,转换成一张有向无环图。 然后对缩点后的图进行正反拓扑,求出必经点。 再看必经点是否在一个点数>=2的强联通分量中。 正反拓扑过程: fs[u]表示从起点到u的路径条数,ft[u]表示从终点到u的路径条数 由乘法原理可知,若一个点满足:fs[u]*ft[u]==fs[t] 这个点是必经点。 细节: 1. 对于存在自环的点,一定不能为最后答案,所以要用self标记一下。 2. 要求用按照遍历顺序输出,要用拓扑序记录一下遍历顺序。 3. 缩点从1出发,而不是将整张图的强联通分量都找出来!! 4. 拓扑的起点为1,终点为n。 5. 缩点后的连边可能会有重边,但这并不影响答案。 6. 路径数会很大,对大质数取模即可(可能会冲突)。 #include<bits/stdc++.h> using namespace std; #define ri register int #define N 1000005 #define ll long long const ll mod=1e9+7; int read() { int x=0,fl=1; char ch=getchar(); while(ch<'0'||ch>'9

tarjan算法

喜欢而已 提交于 2019-11-30 23:09:56
还是有点晦涩难懂 1 vector<int> low; 2 vector<int> dfn; 3 vector<int> father; 4 vector<vector<int>> g; 5 int time = 0; 6 void tarjan(int i, int ifather) 7 { 8 father[i] = ifather; 9 low[i] = time; 10 dfn[i] = time; 11 time++; 12 for (int j = 0; j < g[i].size(); j++) 13 { 14 if (g[i][j] == father[i]) 15 continue; 16 else if (dfn[g[i][j]] == -1) 17 { 18 tarjan(g[i][j], i); 19 low[i] = min(low[i], low[g[i][j]]); 20 } 21 else 22 low[i] = min(low[i], dfn[g[i][j]]); 23 } 24 } 25 vector<vector<int>> criticalConnections(int n, vector<vector<int>>& connections) { 26 vector<int> use(n, -1); 27 vector<vector<int>

【Tarjan】P1726 上白泽慧音

瘦欲@ 提交于 2019-11-30 21:37:18
1 #include<iostream> 2 #include<stack> 3 #include<vector> 4 #include<algorithm> 5 using namespace std; 6 7 int n, m; 8 int dfn[5010], low[5010]; 9 bool vis[5010]; 10 stack<int>s; 11 int cnt; 12 vector<int>to[5010]; 13 int ans; 14 int tot; 15 int res[100010]; 16 int num[100010]; 17 18 void tarjan(int x) 19 { 20 dfn[x] = low[x] = ++cnt; 21 s.push(x); 22 vis[x] = true; 23 for (int i = 0; i < to[x].size(); i++) 24 { 25 if (!dfn[to[x][i]]) 26 { 27 tarjan(to[x][i]); 28 low[x] = min(low[x], low[to[x][i]]); 29 } 30 else if(vis[to[x][i]]) 31 { 32 low[x] = min(low[x], dfn[to[x][i]]); 33 } 34 } 35 if

透彻tarjan

南笙酒味 提交于 2019-11-30 03:27:19
tarjan 求强连通分量: #include<cstdio> #include<iostream> #include<cstdlib> #define N 1000000 #include<vector> vector <int> scc; int sta[N],dfn[N],low[N],in[N],tar[N],tot,tp,cnt; void tarjan(int x) { dfn[x]=low[x]=++tot; sta[++tp]=x; in[x]=1; for(int i=head[x];i;i=e[i].nxt) { if(!dfn[e[i].to]) { tarjan(e[i].to); low[x]=min(low[x],low[e[i].to]); } else if(in[e[i].to]) { low[x]=min(low[x],dfn[e[i].to]); } } if(dfn[x]==low[x]) { int y; cnt++; do{ y=sta[tp--]; in[y]=0; tar[y]=cnt; scc[cnt].push_back(y); }while(x!=y); } } tarjan缩点:   拓扑排序的思想 代码: #include<cstdio> #include<iostream> #include<cstdlib>

bzoj 2208 //2208: [Jsoi2010]连通数

大憨熊 提交于 2019-11-29 23:44:36
bzoj 2208 //2208: [Jsoi2010]连通数 //在线测评地址 https://www.lydsy.com/JudgeOnline/problem.php?id=2208 更多题解,详见 https://blog.csdn.net/mrcrack/article/details/90228694 BZOJ刷题记录 //2208: [Jsoi2010]连通数 //在线测评地址https://www.lydsy.com/JudgeOnline/problem.php?id=2208 //第一个思路,Floyd算法,求最短路径,算法的时间复杂度O(n^3),看了数据范围 N不超过2000,只好作罢 //统计 连通数 时,采用O(n^2)算法即可 //问题是,如何确认2点连通,这个算法的时间复杂度,如何降下来。 //多点的连通问题。 //强连通分量及缩点tarjan算法解析https://blog.csdn.net/acmmmm/article/details/16361033可看此文,手绘图。 //初探tarjan算法(求强连通分量) https://www.luogu.org/blog/styx-ferryman/chu-tan-tarjan-suan-fa-qiu-qiang-lian-tong-fen-liang-post 此文值得一看 /

tarjan缩点——在农场万圣节Trick or Treat on the Farm

ぃ、小莉子 提交于 2019-11-29 18:29:29
一个房间能到另一个房间,有向图,奶牛从自己编号(1到n)的点出发,如果回到以前到过的点就停止,问每头奶牛可以经过几个点; 情况分两种, 一,奶牛在环上,能走的是环的大小,二,一条链连接一个环,大小是链+环; 要预先处理自环的答案(1),还有环的大小是1的(并不在环上的点); 一开始还以为可能出现只有一条链没有环的,但是因为每个点都有一条出边,所以不必担心; #include<cstdio> #include<cstring> #include<stack> #include<algorithm> using namespace std; const int maxn=1e5+10; int pre[maxn*2],last[maxn],other[maxn*2],l; stack<int> s; void add(int x,int y) { l++; pre[l]=last[x]; last[x]=l; other[l]=y; } int belong[maxn]; int qw; int n; int ru[maxn]; int cnt,dfn[maxn],low[maxn]; int next[maxn]; void dfs(int x) { s.push(x); dfn[x]=low[x]=++cnt; ru[x]=1; for(int p=last[x];p;p=pre

受欢迎的牛(Tarjan缩点模板)

爷,独闯天下 提交于 2019-11-29 18:01:46
#include<cstdio> #include<cstring> #include<stack> using namespace std; int n,m,head[10005],vis[10005],dfn[10005], low[10005],color[10005],num[10005],out[10005]; int sum,cnt,tot,jia,ans; stack<int> s; struct edge{ int v,next; }e[50005]; inline void add(int u,int v){ e[++cnt].v=v; e[cnt].next=head[u]; head[u]=cnt; } inline void tarjan(int u){ vis[u]=1; s.push(u); dfn[u]=low[u]=++tot; for(int i=head[u];i!=-1;i=e[i].next){ int v=e[i].v; if(!dfn[v]){ tarjan(v); low[u]=min(low[v],low[u]); } else if(vis[v])low[u]=min(low[v],low[u]); } if(dfn[u]==low[u]){ color[u]=++sum; vis[u]=0; while(1){ int x=s

LeetCode 5192. 查找集群内的「关键连接」

倾然丶 夕夏残阳落幕 提交于 2019-11-29 17:12:07
1. 问题 力扣数据中心有 n 台服务器,分别按从 0 到 n-1 的方式进行了编号。 它们之间以「服务器到服务器」点对点的形式相互连接组成了一个内部集群,其中连接 connections 是无向的。 从形式上讲, connections[i] = [a, b] 表示服务器 a 和 b 之间形成连接。任何服务器都可以直接或者间接地通过网络到达任何其他服务器。 「关键连接」是在该集群中的重要连接,也就是说,假如我们将它移除,便会导致某些服务器无法访问其他服务器。 请你以任意顺序返回该集群内的所有 「关键连接」。 示例 1: 输入:n = 4, connections = [[0,1],[1,2],[2,0],[1,3]] 输出:[[1,3]] 解释:[[3,1]] 也是正确的。 原题链接 ; 2. Tarjan算法 Tarjan 算法是在一个图中查找强连通分量的算法。强连通分量是指,每个顶点皆可由该图上的边抵达其他的每一个点的有向图。 算法的基本思想: 任选一个节点开始进行深度优先搜索(若深度优先搜索结束后仍有未访问的节点,则从中任选一点再次进行)。搜索过程中已访问的节点不再访问。 强连通分量的根: 指深度优先搜索是强连通分量重首个被访问的节点。 为找到根节点,我们给每个节点 v 一个深度优先搜索标号 v.index ,表示第几个被访问的节点。此外,每个节点有一个值 v