Tarjan-有向图
(我到底是咕了多少知识点啊)
在有向图中tarjan主要用来求强连通分量并缩点
一、定义
强连通:如果两个顶点可以相互通达,则称两个顶点 强连通
强连通分量:如果有向图G的每两个顶点都 强连通,称G是一个强连通图。非 强连通图有向图的极大强连通子图,称为强连通分量
树枝边:原图上的边中,在DFS树上由父亲指向儿子的叫树枝边
前向边:由父亲指向儿子以下的其他后代的叫前向边
后向边:由后代指向祖先的边叫后向边
横叉边:一个子树中的点指向另一个子树中的点的边叫横叉边
二、tarjan
用来求强联通分量
基于dfs
每个强连通分量为搜索树中的一颗子树
三、算法
首先要引入两个非常重要的数组:dfn[ ] 和 low[ ]
dfn[ ] :就是一个时间戳(被dfs到的次序)。
low [ ] : 该子树中,且仍在栈中的最小时间戳(即可以到达的图中dfn值最小的点得dfn值)
这个图不一定是一个连通图,所以跑tarjan的时候要枚举每个点
若dfn[ ] == 0,进行深搜
然后对于搜到的点寻找与其有边相连的点,判断这些点是否已经被搜索过,若没有,则进行搜索。若该点已经入栈,说明形成了环,则更新low.
在不断深搜的过程中如果没有路可走了(出边遍历完了),那么就进行回溯,回溯时不断比较low[ ],去最小的low值。如果dfn[x]==low[x]则x可以看作是某一强连通分量子树的根,也说明找到了一个强连通分量,然后对栈进行弹出操作,直到x被弹出。
洛谷缩点板子题
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std; inline int read()
{
int sum = ,p = ;
char ch = getchar();
while(ch < '' || ch > '')
{
if(ch == '-')
p = -;
ch = getchar();
}
while(ch >= '' && ch <= '')
{
(sum *= ) += ch - '';
ch = getchar();
}
return sum * p;
} const int maxn = 1e5+1e4,maxm = 1e5 + 1e4;
int vis[maxn],dfn[maxn],low[maxn],tim;
int ncnt,bel[maxn],sum[maxn],f[maxn];
int cnt,head[maxn],nxt[maxm],to[maxm];
int sta[maxn],top;
int n,m,val[maxn],x[maxm],y[maxm],ans; void add(int a,int b)
{
nxt[++cnt] = head[a];
to[cnt] = b;
head[a] = cnt;
} void tarjan(int x)
{
dfn[x] = low[x] = ++tim;
sta[++top] = x;
vis[x] = ;
for(int i = head[x];i;i = nxt[i])
{
int v = to[i];
if(!dfn[v])
{
tarjan(v);
low[x] = min(low[x],low[v]);
}
else if(vis[v])
low[x] = min(low[x],dfn[v]);
}
if(low[x] == dfn[x])
{
ncnt++;
while(sta[top+] != x)
{
bel[sta[top]] = ncnt;
sum[ncnt] += val[sta[top]];
vis[sta[top--]] = ;
}
}
} void search(int x)
{
if(f[x])
return;
f[x] = sum[x];
int maxsum = ;
for(int i = head[x];i;i = nxt[i])
{
if(!f[to[i]])
search(to[i]);
maxsum = max(maxsum,f[to[i]]);
}
f[x] += maxsum;
} int main()
{
n = read();
m = read();
for(int i = ;i <= n;i++)
val[i] = read();
for(int i = ;i <= m;i++)
{
x[i] = read();
y[i] = read();
add(x[i],y[i]);
}
for(int i = ;i <= n;i++)
if(!dfn[i])
tarjan(i);
memset(head,,sizeof(head));
memset(nxt,,sizeof(nxt));
memset(to,,sizeof(to));
cnt = ;
for(int i = ;i <= m;i++)
{
if(bel[x[i]] != bel[y[i]])
add(bel[x[i]],bel[y[i]]);
}
for(int i = ;i <= ncnt;i++)
if(!f[i])
{
search(i);
ans = max(ans,f[i]);
}
printf("%d",ans);
return ;
}
Tarjan-有向图的更多相关文章
- *转载 Tarjan有向图详解
注意! 文章转自:https://www.cnblogs.com/liwenchi/p/7259306.html,如有造成任何侵权行为,请与我联系.我会在第一时间删除. 不过说实话,这大佬写的真的强, ...
- tarjan有向图的强连通
强连通:在有向图G中,两个顶点间至少存在一条路径,则两个点强连通. 强连通图:在有向图中,每两个顶点都强连通,则有向图G就是一个强连通图. 强连通分量:在非强连通图中的极大强连通子图,就称为强连通分量 ...
- 对Tarjan——有向图缩点算法的理解
开始学tarjan的时候,有关无向图的割点.桥.点双边双缩点都比较容易地理解了,唯独对有向图的缩点操作不甚明了.通过对luoguP2656_采蘑菇一题的解决,大致搞清了tarjan算法的正确性. 首先 ...
- tyvj 1153 间谍网络 tarjan有向图强连通
P1153 - 间谍网络 From ForeverBell Normal (OI)总时限:13s 内存限制:128MB 代码长度限制:64KB 描述 Description 由于外国 ...
- HDU1269迷宫城堡(裸Tarjan有向图求强连通分量个数)
迷宫城堡Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...
- Reachability from the Capital(Codeforces Round #490 (Div. 3)+tarjan有向图缩点)
题目链接:http://codeforces.com/contest/999/problem/E 题目: 题意:给你n个城市,m条单向边,问你需要加多少条边才能使得从首都s出发能到达任意一个城市. 思 ...
- hdu3861他的子问题是poj2762二分匹配+Tarjan+有向图拆点 其实就是求DAG的最小覆盖点
The King’s Problem Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Other ...
- tarjan——有向图、无向图
强连通块只存在于有向无环图DAG中 实际上low[i]的理解是:一个强连通块在dfs搜索树中子树的根节点 //把一个点当成根提溜出来,抖搂抖搂成一棵树 void dfs(int u) { //记录df ...
- 连通分量模板:tarjan: 求割点 && 桥 && 缩点 && 强连通分量 && 双连通分量 && LCA(近期公共祖先)
PS:摘自一不知名的来自大神. 1.割点:若删掉某点后.原连通图分裂为多个子图.则称该点为割点. 2.割点集合:在一个无向连通图中,假设有一个顶点集合,删除这个顶点集合,以及这个集合中全部顶点相关联的 ...
- tarjan图论算法
tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...
随机推荐
- VSCode C语言编程(一)环境搭建
1.安装Visual Studio Code 2. 安装MinGW编译器 有两种方法 方法(1) 打开https://sourceforge.net/projects/mingw-w64/files/ ...
- Codeforces Round #614 (Div. 2) C - NEKO's Maze Game
题目链接:http://codeforces.com/contest/1293/problem/C 题目:给定一个 2*n的地图,初始地图没有岩浆,都可以走, 给定q个询问,每个询问给定一个点(x,y ...
- H5与native 普及
H5与native 普及: H5是基于web,native基于客户端native是使用原生系统内核的,相当于直接在系统上操作.,是我们传统意义上的软件,更加稳定.但是H5的APP先得调用系统的浏览器内 ...
- Codeforces Round #603 (Div. 2) C.Everyone is A Winner!
tag里有二分,非常的神奇,我用暴力做的,等下去看看二分的题解 但是那个数组的大小是我瞎开的,但是居然没有问题233 #include <cstdio> #include <cmat ...
- [SDOI2014] 重建 - 矩阵树定理,概率期望
#include <bits/stdc++.h> #define eps 1e-6 using namespace std; const int N = 55; namespace mat ...
- 在 linux 上运行 oracle sql脚本
方法一 su - oracle //切换到oracle用户模式下 sqlplus /nolog //登录sqlplus connect /as sysdba; //连接orcale @sql脚本路 ...
- 剪切文件或目录命令 - mv
①.命令名称:mv ②.英文原意:move ③.命令所在路径:/bin/mv ④.执行权限:所有用户 ⑤.功能描述:剪切文件.改名 ⑥.语法: mv[原文件或目录][目标目录] 例子:在 tmp目录下 ...
- Maven设置阿里云镜像
<mirrors> <mirror> <id>alimaven</id> <name>aliyun maven</name> & ...
- python多进程编程学习笔记
摘自[https://www.cnblogs.com/chenhuabin/p/10070996.html] by 奥辰 赞
- crontab实践
1.crontab概要 2.crontab使用 3.关键配置信息 3.1如何配置定时任务 4.注意事项 参考 https://www.cnblogs.com/keithtt/p/6946498.htm ...