tarjan算法c语言,tarjan算法板子 - osc_e45irv7l的个人空间 - OSCHINA - 中文开源技术交流社区...

无向图

概念

时间戳

\(dfn[x]\),在深度优先遍历中,按照每个节点第一次被访问的顺序,依次做整数标记

追溯值

\(low[x]\),通过非搜索边能到达的最小时间戳

割边判定法则

无向边\((x,y)\)是割边/桥,当且仅当存在x的一个子节点满足\(dfn[x] < low[y]\)

删除无向边\((x,y)\)后,图断开成两个部分

板子

int dfn[N], low[N], dfcnt;

bool g[M];

void tarjan(int x, int ei) {

dfn[x] = low[x] = ++dfcnt;

for(int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (!dfn[y]) {

tarjan(y, i);

low[x] = min(low[x], low[y]);

if (dfn[x] < low[y]) g[i] = g[i^1] = 1;

}

else if (i != (ei^1)) low[x] = min(low[x], dfn[y]);

}

}

割点判定法则

若x不是根节点,则x是割点当且仅当存在一个子节点y满足\(dfn[x]\leq low[y]\)

若x是根节点,则x是割点当且仅当存在至少两个子节点\(y_1,y_2\)满足上条件

板子

int dfn[N], low[N], dfcnt, rt;

bool g[N];

void tarjan(int x) {

dfn[x] = low[x] = ++dfcnt;

int son = 0;

for (int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (!dfn[y]) {

tarjan(y);

low[x] = min(low[x], low[y]);

if (dfn[x] <= low[y]) {

son++;

if (x != rt || son > 1) g[x] = 1;

}

}

else low[x] = min(low[x], dfn[y]);

}

}

点双联通分量

对于,每个点双中来说,图里是不存在割点的

板子

int dfn[N], low[N], dfcnt, sta[N], top, cnt;

vector dcc[N];

bool g[N];

void tarjan(int x, int rt) {

dfn[x] = low[x] = ++dfcnt;

sta[++top] = x;

int son = 0;

for (int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (!dfn[y]) {

tarjan(y);

low[x] = min(low[x], low[y]);

if (dfn[x] <= low[y]) {

son++;

if (x != rt || son > 1) g[x] = 1;

dcc[++cnt].clear();

while (1) {

int z = sta[top--];

dcc[cnt].push_back(z);

if (y == z) break;

}

dcc[cnt].push_back(x);

}

}

else low[x] = min(low[x], dfn[y]);

}

}

边双联通分量

对于一个边双,任意两个点都有两条不重合的路径

板子

int dfn[N], low[N], dfcnt;

bool g[M];

void tarjan(int x, int ei) {

dfn[x] = low[x] = ++dfcnt;

for(int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (!dfn[y]) {

tarjan(y, i);

low[x] = min(low[x], low[y]);

if (dfn[x] < low[y]) g[i] = g[i^1] = 1;

}

else if (i != (ei^1)) low[x] = min(low[x], dfn[y]);

}

}

int n, m, d[N], b[N], cnt, ans;

void dfs(int x) {

b[x] = cnt;

for(int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (b[y] || g[i]) continue;

dfs(y);

}

}

int main() {

//~~~

for(int i = 1; i <= n; i++)

if (!dfn[i]) tarjan(i, 0);

for(int i = 1; i <= n; i++)

if (!b[i]) cnt++, dfs(i);

//~~~

return 0;

}

有向图

有向图的强联通分量

在一个强联通分量中,存在x到y的路径,就存在y到x的路径

板子

void tarjan(int x) {

dfn[x] = low[x] = ++dfcnt;

s[++top] = x;

for(int i = head[x]; i; i = e[i].next) {

int y = e[i].t;

if (!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]);

else if (!b[y]) low[x] = min(low[x], dfn[y]);

}

if (dfn[x] == low[x]) {

cnt++;

while(1) {

int y = s[top--];

b[y] = cnt;

size[cnt]++;

if (x == y) break;

}

}

}

例题

luoguP3387缩点

代码

#include

#include

#include

#include

using namespace std;

const int N = 1e4+5, M = 1e5+5;

struct side { int t, next; } e[M][2];

int head[N][2], tot[2];

void add(int x, int y, int k) {

e[++tot[k]][k].next = head[x][k];

head[x][k] = tot[k];

e[tot[k]][k].t = y;

}

int n, m, w[N], r[N], d[N], ans;

int dfn[N], low[N], dfcnt, sta[N], top, cnt, bel[N], sum[N];

void tarjan(int x) {

dfn[x] = low[x] = ++dfcnt;

sta[++top] = x;

for (int i = head[x][0]; i; i = e[i][0].next) {

int y = e[i][0].t;

if (!dfn[y]) tarjan(y), low[x] = min(low[x], low[y]);

else if (!bel[y]) low[x] = min(low[x], dfn[y]);

}

if (dfn[x] == low[x]) {

cnt++;

while (1) {

int y = sta[top--];

bel[y] = cnt;

sum[cnt] += w[y];

if (x == y) break;

}

}

}

queue q;

int tuopu() {

for (int i = 1; i <= cnt; i++)

if (!r[i]) q.push(i), d[i] = sum[i];

while (!q.empty()) {

int x = q.front(); q.pop();

for (int i = head[x][1]; i; i = e[i][1].next) {

int y = e[i][1].t;

d[y] = max(d[y], d[x] + sum[y]);

if (--r[y] == 0) q.push(y);

}

}

for (int i = 1; i <= cnt; i++)

ans = max(ans, d[i]);

return ans;

}

int main() {

scanf("%d%d", &n, &m);

for (int i = 1; i <= n; i++)

scanf("%d", &w[i]);

for (int i = 1; i <= m; i++) {

int x, y;

scanf("%d%d", &x, &y);

add(x, y, 0);

}

for (int i = 1; i <= n; i++)

if (!dfn[i]) tarjan(i);

for (int x = 1; x <= n; x++)

for (int i = head[x][0]; i; i = e[i][0].next) {

int y = e[i][0].t;

if (bel[x] != bel[y])

r[bel[y]]++, add(bel[x], bel[y], 1);

}

printf("%d\n", tuopu());

return 0;

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/574257.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

流和文件

流&#xff1a;流是数据的传输方式&#xff1b;C程序处理一个流而不是直接处理文件。你声明一个FILE *fp &#xff0c;并把fopen(某个文件)返回的值赋予fp这两个动作就相当于建立了一个水龙头&#xff0c;当你用getc(fp)之类的输入函数读取文件字符时就相当于拧开了水龙头&…

小球进盒子C语言,N个小球放进M个盒子算法-Go语言中文社区

N个小球放入M个盒子共有多少种方法&#xff0c;并输出的算法设计&#xff1a;算法思路1 &#xff1a;暴力填充盒子每个小球都可能放入M个盒子的任意一个&#xff0c;所以直接根据小球个数做递归即可,然后将存储放入hash中排重//TODO算法思路2 &#xff1a;递归填充盒子即&#…

r语言c5.0要求因子输出,R语言中因子的创建与使用

原标题&#xff1a;R语言中因子的创建与使用因子在R语言中可以用来表示名义型变量或有序变量。名义变量一般表示类别&#xff0c;如性别&#xff0c;种族等等。有序变量是有一定排序顺序的变量&#xff0c;如职称&#xff0c;年级等等。在R语言中&#xff0c;名义变量和有序变量…

WinForm中使用AnyCAD三维控件 の 初始化

在WinForm中可以方便的集成AnyCAD.Net三维控件&#xff0c;只需要以下几部即可完成。 一、添加DLL程序集 AnyCAD.Foundation.Net.dll AnyCAD.Presentation.Net.dll AnyCAD.Exchange.Net.dll 二、初始化控件 1.首先创建一个窗体 2.在窗体上放置一个Panel用来放置三维控件 3.初始…

linux中nodejs后台运行工具forever

forever让nodejs应用后台执行 命令如下&#xff1a; forever start ./bin/www nodejs一般是当成一条用户命令执行的&#xff0c;当用户断开客户连接&#xff0c;运用也就停了&#xff0c;很烦人。如何让nodejs应用当成服务&#xff0c;在后台执行呢&#xff1f; 最简单的办法(不…

android启动其他app的服务器,Android中通过外部程序启动App的三种方法

这篇文章主要介绍了Android中通过外部程序启动App的三种方法,本文讲解了直接通过包名、通过自定义的Action、通过Scheme三种方法,并分别给出操作代码,需要的朋友可以参考下第一种&#xff1a;直接通过包名&#xff1a;复制代码 代码如下:Intent LaunchIntent getPackageManage…

linux date 天之前,linux date命令前后几天的推导

linux date使用(前后几天时间推导)在Linux系统 中&#xff0c;可以采用如下方法&#xff1a;1) 取之前的时间&#xff1a;date -d "a day ago" %Y%m%d 取出前1天的系统时间date -d "2 days ago" %Y%m%d 取出前2天的系统时间2) 取之后的时间&#xff1a;dat…

各种封装——封装getClass

因为用Class获取元素时&#xff0c;有兼容性问题&#xff0c;需要分情况获取 显示判断是否可以用getElementsByClassName&#xff0c;若是不介意用就要先获取全部的元素&#xff0c;在用正则判断 function getClass(oParent,sClass){if(oParent.getElementsByClassName){return…

android提示程序正在执行,Android中获取正在运行的进程(一)

关于android中应用程序正在运行的进程有下面几种&#xff1a;1-包含services的进程&#xff0c;2-不包含services的进程&#xff0c;3-杀死应用时有些进程被init回收(类似于僵尸进程)&#xff0c;ppid变为1&#xff0c;无法通过android 应用层代码获得的进程。这些进程可能是应…

jta 知识

JTA知识&#xff08;转载原文地址&#xff1a;http://blog.csdn.net/it_man/article/details/7230215&#xff09; Java Transaction API&#xff0c;译为Java事务API。JTA允许应用程序执行分布式事务处理——在两个或多个网络计算机资源上访问并且更新数据。JTA主要用于分布式…

android l usb调试,你居然还不会手机usb调试?5个方法,让你轻松学会设置!

原标题&#xff1a;你居然还不会手机usb调试&#xff1f;5个方法&#xff0c;让你轻松学会设置&#xff01;最近有位朋友将手机连接电脑的时候&#xff0c;遇到了提示打开手机的USB调试模式&#xff0c;却不知道怎么操作。其实&#xff0c;不同手机的usb调试打开的方式都会有所…

深入沟通的重要性——《大道至简》第四章读后感

我们都知道&#xff0c;一个新发明如果不被人们所需要&#xff0c;那只是一个失败品。一篇文章的观点如果不被人们所接受&#xff0c;那么就算文笔再好&#xff0c;也只是一张废纸。同样的&#xff0c;一个与客户需求不符的程序&#xff0c;哪怕它的架构再好&#xff0c;都只是…

鸿蒙os芯片,没有了芯片,华为能靠鸿蒙OS系统打出差异化吗?

原标题&#xff1a;没有了芯片&#xff0c;华为能靠鸿蒙OS系统打出差异化吗&#xff1f;华为今天要和大家说的手机产品是华为&#xff0c;在目前的市场中&#xff0c;华为手机的影响力是非常大的&#xff0c;并且获得了十分不错的销量&#xff0c;甚至在最近一段时间销量超过三…

html5 canvas 不兼容safari浏览器_HTML5简介

HTML5 是继 HTML4.01 和 XHTML1.0 之后的超文本标记语言的最新版本。它是由一群自由思想者组成的团队设计出来&#xff0c;并最终实现多媒体支持、交互性、更加智能的表单&#xff0c;以及更好的语义化标记。HTML5 并不仅仅是 HTML 规范的最新版本&#xff0c;而是一系列用来制…

html5置顶标签css样式,html5 header标签 html header css布局教程 /header

在HTML5版本之前习惯使用div标签布局网页&#xff0c;在HTML5在DIV标签基础上新增header标签元素。也叫“”头部标签。以前我们在div css布局中常常把网页大致分为头部、内容、底部。对于大结构我们常常使用div里加id进行布局。而头部常常使用正应为大家公认html布局中对“head…

DML数据操作语言练习

--创建表T_HQ_BM2 --create table t_hq_bm2 as select * from t_hq_bm; commit;--添加行内容 --insert into t_hq_bm2 values (107,研发部,147258369); commit;--删除部门编码为107的行 --delete t_hq_bm2 where bumenbm 107; commit;--添加行内容 --insert into t_hq_bm2 (bu…

第八届育才杯机器人比赛_赛场、名单公布!南海区第八届“献血者杯”羽毛球公开赛“羽”你相约本周六...

主办单位&#xff1a;南海区献血办、南海血站协办单位&#xff1a;南海区羽毛球协会为进一步扩大无偿献血宣传&#xff0c;感恩南海区献血者&#xff0c;活跃无偿献血者的文体生活&#xff0c;打造一个南海区无偿献血者交流的平台&#xff0c;共同营造“运动、健康、献血、快乐…

2021届安徽高考成绩查询,安徽2021年高考成绩什么时候公布

据安徽省教育招生考试院透露&#xff0c;安徽预计将于6月23日公布各批次录取分数线、考生成绩。2021年安徽高考成绩查询入口2021年高考录取方法1、普通高校的招生录取工作在教育部和省高校招生委员会的领导下&#xff0c;由省考试院组织实施。2、省高校招生委员会根据当年高校在…

BroadcastReceiver 广播机制详解

BroadcastReceiver也就是“广播接收者”的意思&#xff0c;顾名思义&#xff0c;它就是用来接收来自系统和应用中的广播。 在Android系统中&#xff0c;广播体现在方方面面&#xff0c;例如当开机完成后系统会产生一条广播&#xff0c;接收到这条广播就能实现开机启动服务的功能…

会话管理 轻量php框架_SpringSecurity+JWT权限管理训练营-1基于RBAC模型的权限管理系统...

1.什么是权限管理系统&#xff1f;权限管理是一个几乎所有后台系统的都会涉及的一个重要组成部分&#xff0c;可以说是后台项目的基本功&#xff0c;主要目的是对整个后台管理系统进行权限的控制&#xff0c;而针对的对象是员工&#xff0c;避免因权限控制缺失或操作不当引发的…