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

在有向图中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. 【动态规划】【C/C++】简单的背包问题

    简单的背包问题 背包问题动态规划中非常经典的一个问题,本文只包含01背包,完全背包和多重背包.更加详尽的背包问题的讲解请参考崔添翼大神的<背包九讲> 简单的01背包 问题导入:新年到了,m ...

  2. python:if else 语句

    #!/usr/bin/python# -*- coding:utf-8 -*- import os fileName1 = 'a.txt'if os.path.exists(fileName1): f ...

  3. 线段树的树状数组大小为什么是4*maxn

    以下方建树代码为例,r数组表述原始数据,t表述tree也就是树状数组 void make(int left,int right,int num)//创建线段树 { t[num].l=left; t[n ...

  4. Java中new一个子类对象的同时并不会自动创建一个父类对象

    首先重申一个概念:子类会继承父类所有非私有成员变量和方法,包括父类的构造方法 当创建一个子类对象时,首先开辟内存,然后调用类的构造函数,这里的构造函数由两部分组成,一部分是从父类继承而来的父类的构造方 ...

  5. 在CentOS上通过Docker方式安装Redis

    在CentOS上通过Docker方式安装Redis 首先保证已经安装docker. 拖拽redis镜像 docker pull redis 启动redis docker run -p 6379:637 ...

  6. 【Python】文本进度条

    1.0代码: import time#引入time库 scale=10#文本进度条宽度 print("------执行开始------") for i in range(scale ...

  7. FPM 0.08不能运行破解办法……

    FPM_0.080.rar 破解办法:用UltraEdit打开FPM.exe,查找"33 C0 E9 F2"(注意中间有空格)将33改为8B,F2改为00

  8. mysql 1130 Navicat for MySQL 连接MySQL 8.0 出现1130错误

    可能是帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑登入MySQL后,更改"MySQL"数据库"user"表里的&q ...

  9. Oracle 12.2.0.1 Installation Fails With "PRVG-0449"

    Mac 电脑虚拟机 Parallels 中进行Oracle 12.2.0.1 数据库软件安装时,预环境检查过程中,提示堆栈大小限制[失败],即使修复问题依然如故. Oracle 12.2.0.1 In ...

  10. Python + Selenium +Chrome 批量下载网页代码修改【新手必学】

    Python + Selenium +Chrome 批量下载网页代码修改主要修改以下代码可以调用 本地的 user-agent.txt 和 cookie.txt来达到在登陆状态下 批量打开并下载网页, ...