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 ...
随机推荐
- 【动态规划】【C/C++】简单的背包问题
简单的背包问题 背包问题动态规划中非常经典的一个问题,本文只包含01背包,完全背包和多重背包.更加详尽的背包问题的讲解请参考崔添翼大神的<背包九讲> 简单的01背包 问题导入:新年到了,m ...
- python:if else 语句
#!/usr/bin/python# -*- coding:utf-8 -*- import os fileName1 = 'a.txt'if os.path.exists(fileName1): f ...
- 线段树的树状数组大小为什么是4*maxn
以下方建树代码为例,r数组表述原始数据,t表述tree也就是树状数组 void make(int left,int right,int num)//创建线段树 { t[num].l=left; t[n ...
- Java中new一个子类对象的同时并不会自动创建一个父类对象
首先重申一个概念:子类会继承父类所有非私有成员变量和方法,包括父类的构造方法 当创建一个子类对象时,首先开辟内存,然后调用类的构造函数,这里的构造函数由两部分组成,一部分是从父类继承而来的父类的构造方 ...
- 在CentOS上通过Docker方式安装Redis
在CentOS上通过Docker方式安装Redis 首先保证已经安装docker. 拖拽redis镜像 docker pull redis 启动redis docker run -p 6379:637 ...
- 【Python】文本进度条
1.0代码: import time#引入time库 scale=10#文本进度条宽度 print("------执行开始------") for i in range(scale ...
- FPM 0.08不能运行破解办法……
FPM_0.080.rar 破解办法:用UltraEdit打开FPM.exe,查找"33 C0 E9 F2"(注意中间有空格)将33改为8B,F2改为00
- mysql 1130 Navicat for MySQL 连接MySQL 8.0 出现1130错误
可能是帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑登入MySQL后,更改"MySQL"数据库"user"表里的&q ...
- Oracle 12.2.0.1 Installation Fails With "PRVG-0449"
Mac 电脑虚拟机 Parallels 中进行Oracle 12.2.0.1 数据库软件安装时,预环境检查过程中,提示堆栈大小限制[失败],即使修复问题依然如故. Oracle 12.2.0.1 In ...
- Python + Selenium +Chrome 批量下载网页代码修改【新手必学】
Python + Selenium +Chrome 批量下载网页代码修改主要修改以下代码可以调用 本地的 user-agent.txt 和 cookie.txt来达到在登陆状态下 批量打开并下载网页, ...