tarjan算法笔记
tarjan算法可以用来求强连通块的块数,判断条件是low[x] = dfn[x];
注意点:缩点后是将强连通块当作点,所以重建图的时候,发现原图2点不在同一强连通块就可以按照原图的方向链接2个超级点。
建图可以能有重边但是大部分不会对解题产生影响。如果有需要可以用set去重。
tarjan 当 low[x] = dfn[x] 时,弹出 x 包括x前面的元素,这些元素共同组成一个量连通块。不要忘记标记他们已经被弹出了
vis[stack[top--]] = 0; // 弹出
P3387 【模板】缩点
#include<cstring>
#include<queue>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<cmath>
#include<string>#define ll long long
#define max(a,b) a > b ? a : b
#define min(a,b) a < b ? a : b
#define me(a,b) memset(a, b, sizeof(a))
#define iosos ios::sync_with_stdio(false)
#define fo(a,b,c) for(int a = b; a < c; a++)using namespace std;const int maxn = 1e5 + 10;
const int maxm = maxn << 1;
const int inf = 0x7f7f7f7f;
int h[maxn], h1[maxn], p, p1;int point[maxn], w[maxn], color[maxn], sum;int n, m;int dfn[maxn], low[maxn], cnt;int stack[maxn], top;int vis[maxn];int deg[maxn];int dp[maxn];struct edge {int nes,u, to;}e[maxm], e1[maxm];inline void add(int u, int v) {e[p].nes = h[u], e[p].to = v, e[p].u = u, h[u] = p++;
}inline void add1(int u, int v) {e1[p1].nes = h1[u], e1[p1].to = v, h1[u] = p1++;
}void tarjan(int x) {dfn[x] = low[x] = ++cnt;vis[x] = 1; stack[++top] = x;for(int i = h[x]; ~i; i= e[i].nes) {int v = e[i].to;if(!dfn[v]){tarjan(v);low[x] = min(low[x], low[v]);} else if(vis[v]) {low[x] = min(low[x], low[v]);}} if(dfn[x] == low[x]) {++sum;while(stack[top+1] != x) {color[stack[top]] = sum; //标记块 w[sum] += point[stack[top]]; //合并块 vis[stack[top--]] = 0; // 弹出 }}
}int main() {iosos;me(h,-1);me(h1, -1);cin>>n>>m;fo(i,1,n+1) cin>>point[i];fo(i, 0, m) {int u, v;cin>>u>>v;add(u, v);} fo(i,1,n+1) if(!dfn[i]) tarjan(i); fo(i, 0, p) { //枚举所有边 int u = e[i].u, v = e[i].to;if(color[u] != color[v]) { // 如果原图上的2点不在同一超级点 则链接他们所在的超级点 add1(color[u], color[v]); //重新建图 deg[color[v]]++; //超级点入读加1 }}queue<int > q;fo(i,1,sum+1) dp[i] = w[i];for(int i = 1; i <= sum; i++) { //讲入读为0的超级点加入 if(!deg[i]) {q.push(i);}}while(!q.empty()) { //边top边dp 无后效 int u = q.front(); q.pop();for(int i = h1[u]; ~i; i = e1[i].nes) {int v = e1[i].to;dp[v] = max(dp[v], w[v] + dp[u]);--deg[v];if(deg[v] == 0) q.push(v);}}int ans = 0;fo(i,1,sum+1) ans = max(ans, dp[i]);cout<<ans;return 0;
}
tarjan算法笔记相关推荐
- tarjan算法_【朝夕的ACM笔记】树上问题-最近公共祖先-倍增算法
[朝夕的ACM笔记]目录与索引 最近公共祖先-倍增算法 一.基本概念 最近公共祖先问题:对于给定的一颗有根树,求其两个节点的最近公共祖先. 祖先:节点本身.节点的父亲.节点父亲的父亲--都是该节点的祖 ...
- Tarjan算法学习笔记
一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法. [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(strongly connected ...
- 0x66.图论 - Tarjan算法与无向图连通性
目录 一.无向图的割点与桥 割点 桥/割边 时间戳 搜索树 追溯值 二.割边判定法则 三.割点判定法则 1.luogu P3388 [模板]割点(割顶) 2.luogu P3469 [POI2008] ...
- C++算法篇:DFS超详细解析(2)--- tarjan算法求无向图割边
<<<上一篇 系列文章目录 ①:无向图基本概念 ②:tarjan算法求无向图割边 前言 第一次写算法,讲得肯不透彻,有误还请指教awa 文章目录 系列文章目录 一.回顾 二.tarj ...
- Hello Tarjan ---- Tarjan算法小结
一种由Robert Tarjan提出的求解有向图强连通分量的线性时间的算法. ------百度百科 解读一下这句话,Tarjan算法可以解决存在强连通分量的图,而且是在线性时间内解决.所以,不得不% ...
- 金蝉素数c语言,算法笔记_204:第四届蓝桥杯软件类决赛真题(Java语言C组)
前言:以下代码仅供参考,若有错误欢迎指正哦~ 1好好学习 汤姆跟爷爷来中国旅游.一天,他帮助中国的小朋友贴标语.他负责贴的标语是分别写在四块红纸上的四个大字:"好.好.学.习".但 ...
- tarjan算法不是很懂先mark一下。
前面为转载的.后面是自己的理解. 三种tarjan算法(上) .这篇算是做一个总结吧. 求强连通分量 求无向图的割和桥 最近公共祖先 求强连通分量 基本概念: 强连通是有向图才有的概念. ...
- Tarjan算法应用 (割点/桥/缩点/强连通分量/双连通分量/LCA(最近公共祖先)问题)...
转载自:http://hi.baidu.com/lydrainbowcat/blog/item/2194090a96bbed2db1351de8.html 基本概念: 1.割点:若删掉某点后,原连通图 ...
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
最新文章
- Windows Server Update 失败后,怎么恢复
- Unet实现图像分割(二)
- python爬取图片教程-推荐|Python 爬虫系列教程一爬取批量百度图片
- [POJ 2329] Nearest number-2
- OTA和Recovery系统升级流程介绍
- JS基础语法(03)-前自增与后自增区别
- Pixhawk原生固件PX4之顶层软件结构
- js 中转换成list集合_程序员:java集合介绍-List,具说很详细,你不来看看?
- mysql远程备份工具_innobackupex实现MySQL远程备份
- python 爬取全量百度POI
- Python+django网页设计入门(15):公用模板设计与使用
- 《我的世界》AI大战降临:6000万帧超大数据集已发布,NeurIPS 19向你约战
- 异常——Python
- Runloop与autoreleasePool联系
- Java 概述、Java语言的特点、什么是跨平台性、Java语言平台版本、什么是jdk,jre、JDK和JRE的下载安装...
- 各种 IntelliJ IDEA 酷炫插件推荐
- 1521 一维战舰 水题
- 在职复习考研计算机408,考研初试复习经验分享(计算机408)
- 空间|时间|对象 圈人 + 目标人群透视 - 暨PostgreSQL 10与Greenplum的对比和选择
- ubuntu 下浏览器中打开网页乱码解决