(我到底是咕了多少知识点啊)

在有向图中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-有向图的更多相关文章

  1. *转载 Tarjan有向图详解

    注意! 文章转自:https://www.cnblogs.com/liwenchi/p/7259306.html,如有造成任何侵权行为,请与我联系.我会在第一时间删除. 不过说实话,这大佬写的真的强, ...

  2. tarjan有向图的强连通

    强连通:在有向图G中,两个顶点间至少存在一条路径,则两个点强连通. 强连通图:在有向图中,每两个顶点都强连通,则有向图G就是一个强连通图. 强连通分量:在非强连通图中的极大强连通子图,就称为强连通分量 ...

  3. 对Tarjan——有向图缩点算法的理解

    开始学tarjan的时候,有关无向图的割点.桥.点双边双缩点都比较容易地理解了,唯独对有向图的缩点操作不甚明了.通过对luoguP2656_采蘑菇一题的解决,大致搞清了tarjan算法的正确性. 首先 ...

  4. tyvj 1153 间谍网络 tarjan有向图强连通

    P1153 - 间谍网络 From ForeverBell    Normal (OI)总时限:13s    内存限制:128MB    代码长度限制:64KB 描述 Description 由于外国 ...

  5. HDU1269迷宫城堡(裸Tarjan有向图求强连通分量个数)

    迷宫城堡Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submiss ...

  6. Reachability from the Capital(Codeforces Round #490 (Div. 3)+tarjan有向图缩点)

    题目链接:http://codeforces.com/contest/999/problem/E 题目: 题意:给你n个城市,m条单向边,问你需要加多少条边才能使得从首都s出发能到达任意一个城市. 思 ...

  7. hdu3861他的子问题是poj2762二分匹配+Tarjan+有向图拆点 其实就是求DAG的最小覆盖点

    The King’s Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Other ...

  8. tarjan——有向图、无向图

    强连通块只存在于有向无环图DAG中 实际上low[i]的理解是:一个强连通块在dfs搜索树中子树的根节点 //把一个点当成根提溜出来,抖搂抖搂成一棵树 void dfs(int u) { //记录df ...

  9. 连通分量模板:tarjan: 求割点 &amp;&amp; 桥 &amp;&amp; 缩点 &amp;&amp; 强连通分量 &amp;&amp; 双连通分量 &amp;&amp; LCA(近期公共祖先)

    PS:摘自一不知名的来自大神. 1.割点:若删掉某点后.原连通图分裂为多个子图.则称该点为割点. 2.割点集合:在一个无向连通图中,假设有一个顶点集合,删除这个顶点集合,以及这个集合中全部顶点相关联的 ...

  10. tarjan图论算法

    tarjan图论算法 标签: tarjan 图论 模板 洛谷P3387 [模板]缩点 算法:Tarjan有向图强连通分量+缩点+DAGdp 代码: #include <cstdio> #i ...

随机推荐

  1. 安装vmware tools后仍然不能拖拽文件

    运行/usr/bin/vmware-user文件 ./vmware-user

  2. Java流,文件和I/O

    java.io包中包含几乎所有可能永远需要在Java中执行输入和输出(I/ O)类.所有这些数据流代表一个输入源和输出目标. java.io包中的流支持多种数据,如基本类型,对象,本地化的字符等 流可 ...

  3. hdu 5917

    题意:给你一个无向图,问图中有多少个符合条件的集合?条件为这个集合里面存在一个子集(大小>=3)为团或者都是孤立点.答案mod1e9+7: 根据 Ramsey定理,大于等于6个的集合,肯定存在一 ...

  4. gets(), getline(), cin.getline()

    gets(str), getline(cin, s), cin.getline(str, len),这三个函数都是读入一行字符串的函数,下面是这三个函数的区别 1. gets() 函数是 C 语言的函 ...

  5. C语言-防止输入字母

    今天群里一位小伙伴问了一个关于scanf函数的问题: scanf("%d", &n); 这个代码怎么防止输入字母? 因为他下面是判断n是否为质数,所以这里肯定有个判断,不然 ...

  6. Educational Codeforces Round 80 A-E简要题解

    contest链接:https://codeforces.com/contest/1288 A. Deadline 题意:略 思路:根据题意 x + [d/(x+1)] 需要找到一个x使得上式小于等于 ...

  7. php核心技术与最佳实践--- oop

    <?php /** * Created by PhpStorm. * User: cl * Date: 2019/8/12 * Time: 7:08 */ /*oop*/ class Perso ...

  8. LUT

    FPGA大多为LUT+寄存器的够,实现工艺为SRAM:寄存器很好理解,存储器的一种,用于存储指令和数据,多位于CPU内.拿什么是LUT呢? LUT:即Look up table,查找表,其本质是一个R ...

  9. 第三十二篇 玩转数据结构——AVL树(AVL Tree)

          1.. 平衡二叉树 平衡二叉树要求,对于任意一个节点,左子树和右子树的高度差不能超过1. 平衡二叉树的高度和节点数量之间的关系也是O(logn) 为二叉树标注节点高度并计算平衡因子 AVL ...

  10. Android Studio 初级控件笔记

    Android支持的像素单位 Android支持的像素单位有:px(像素).in(英寸).mm(毫米).pt(磅,1/72英寸).dp(与设备无关的显示单位).dip(就是dp).sp(用于设置字体大 ...