tarjan图论算法
tarjan图论算法
标签: tarjan 图论 模板
洛谷P3387 【模板】缩点

算法:Tarjan有向图强连通分量+缩点+DAGdp
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#define psk push_back
using namespace std;
const int MAXN = 1e5 + 50;
int dfn[MAXN], low[MAXN], dfscnt = 0, scccnt = 0;
int sccnum[MAXN], s[MAXN], in[MAXN], top = 0;
int p0[MAXN], p[MAXN], d[MAXN];
vector<int> G[MAXN], G0[MAXN];
queue<int> q;
inline int read()
{
int res = 0, f = 1;
char ch;
ch = getchar();
while(!isdigit(ch)){
if(ch == '-')
f = -1;
ch = getchar();
}
while(isdigit(ch)){
res = res * 10 + ch - 48;
ch = getchar();
}
return f * res;
}
void tarjan(int now)
{
dfn[now] = low[now] = ++ dfscnt;
s[top ++] = now;
for(int i = 0; i < G0[now].size(); i ++){
int v = G0[now][i];
if(!dfn[v]){
tarjan(v);
low[now] = min(low[now], low[v]);
}
else if(!sccnum[v])
low[now] = min(low[now], dfn[v]);
}
if(low[now] == dfn[now]){
scccnt ++;
do{
sccnum[s[-- top]] = scccnt;
}while(s[top] != now);
}
return;
}
int topoo()
{
for(int i = 1; i <= scccnt; i ++)
if(!in[i]){
d[i] = p[i];
q.push(i);
}
while(!q.empty()){
int u = q.front();q.pop();
for(int i = 0; i < G[u].size(); i ++){
int v = G[u][i];
if(d[v] < d[u] + p[v])
d[v] = d[u] + p[v];
in[v] --;
if(!in[v])
q.push(v);
}
}
return *max_element(d + 1, d + 1 + scccnt);
}
int main()
{
int n, m;
n = read(), m = read();
for(int i = 1; i <= n; i ++)
p0[i] = read();
for(int i = 0; i < m; i ++){
int u, v;
u = read(), v = read();
G0[u].psk(v);
}
for(int i = 1; i <= n; i ++)
if(!dfn[i])
tarjan(i);
for(int i = 1; i <= n; i ++){
p[sccnum[i]] += p0[i];
for(int j = 0; j < G0[i].size(); j ++){
int v = G0[i][j];
if(sccnum[i] == sccnum[v])
continue;
G[sccnum[i]].psk(sccnum[v]);
in[sccnum[v]] ++;
}
}
printf("%d", topoo());
return 0;
}
洛谷P3388 【模板】割点(割顶)

算法:tarjan求无向图割点割边
代码:
#include <cstdio>
#include <cstring>
#include <vector>
#include <iostream>
#define pbk push_back
using namespace std;
const int MAXN = 1e5 + 50;
int dfn[MAXN], low[MAXN], n, m;
int dfscnt = 0, iscut[MAXN];
vector<int> G[MAXN];
inline int read()
{
int res = 0, f = 1;
char ch;
ch = getchar();
while(!isdigit(ch)){
if(ch == '-')
f = -1;
ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + ch - 48;
ch = getchar();
}
return f * res;
}
void tarjan(int now, int rt)
{
int chcnt = 0;
dfn[now] = low[now] = ++ dfscnt;
for(int i = 0; i < G[now].size(); i ++){
int v = G[now][i];
if(!dfn[v]){
tarjan(v, rt);
low[now] = min(low[now], low[v]);
if(now == rt)
chcnt ++;
else if(low[v] >= dfn[now])
iscut[now] = 1;
}
else
low[now] = min(low[now], dfn[v]);
}
if(chcnt >= 2)
iscut[now] = 1;
return;
}
int main()
{
int n, m, tot = 0;
n = read(), m = read();
for(int i = 0; i < m; i ++){
int u, v;
u = read(), v = read();
G[u].pbk(v);
G[v].pbk(u);
}
for(int i = 1; i <= n; i ++)
if(!dfn[i])
tarjan(i, i);
for(int i = 1; i <= n; i ++)
if(iscut[i])
tot ++;
printf("%d\n", tot);
for(int i = 1; i <= n; i ++)
if(iscut[i])
printf("%d ", i);
return 0;
}
求无向图边双连通分量
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#define pbk push_back
using namespace std;
const int MAXN = 1e5 + 50;
vector<int> G[MAXN], bcc[MAXN];
int low[MAXN], dfn[MAXN], bnum[MAXN], s[MAXN];
int n, m, top = 0, dfscnt = 0, bcnt = 0;
inline int read()
{
int res = 0, f = 1;
char ch;
ch = getchar();
while(!isdigit(ch)){
if(ch == '-')
f = -1;
ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + ch - 48;
ch = getchar();
}
return f * res;
}
void tarjan(int now, int fa)
{
dfn[now] = low[now] = ++ bcnt;
s[top ++] = now;
int flag = 0;
for(int i = 0; i < G[now].size(); i ++){
int v = G[now][i];
if(v == fa && !flag){
flag = 1;
continue;
}
if(!dfn[v]){
tarjan(v, now);
low[now] = min(low[now], low[v]);
}
else if(!bnum[v])
low[now] = min(low[now], dfn[v]);
}
if(low[now] == dfn[now]){
bcnt ++;
do{
bnum[s[-- top]] = bcnt;
bcc[bcnt].pbk(s[top]);
}while(s[top] != now);
}
return ;
}
int main()
{
n = read(), m = read();
for(int i = 0; i < m; i ++){
int u, v;
u = read(), v = read();
G[u].pbk(v);
G[v].pbk(u);
}
for(int i = 1; i <= n; i ++)
if(!dfn[i])
tarjan(i, 0);
printf("%d\n", bcnt);
for(int i = 1; i <= bcnt; i ++){
printf("%d ", i);
for(int j = 0; j < bcc[i].size(); j ++)
printf("%d ", bcc[i][j]);
printf("\n");
}
return 0;
}
求无向图点双连通分量
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
#include <algorithm>
#include <iostream>
#define pbk push_back
using namespace std;
const int MAXN = 1e5 + 50;
int low[MAXN], dfn[MAXN], n, m;
int s[MAXN], top = 0, bcnt = 0, dfscnt = 0;
vector<int> G[MAXN], bcc[MAXN];
inline int read()
{
int res = 0, f = 1;
char ch;
ch = getchar();
while(!isdigit(ch)){
if(ch == '-')
f = -1;
ch = getchar();
}
while(isdigit(ch)){
res = (res << 3) + (res << 1) + ch - 48;
ch = getchar();
}
return f * res;
}
void tarjan(int now, int rt)
{
low[now] = dfn[now] = ++ bcnt;
s[top ++] = now;
if(now == rt && !G[now].size()){
bcc[++ bcnt].pbk(s[-- top]);
return ;
}
for(int i = 0; i < G[now].size(); i ++){
int v = G[now][i];
if(!dfn[v]){
tarjan(v, rt);
low[now] = min(low[now], low[v]);
if(low[v] >= dfn[now]){
do{
bcnt ++;
bcc[bcnt].pbk(s[--top]);
}while(s[top] != v);
bcc[bcnt].pbk(now);
}
}
else
low[now] = min(low[now], dfn[v]);
}
return;
}
int main()
{
n = read(), m = read();
for(int i = 0; i < m; i ++){
int u, v;
u = read(), v = read();
G[u].pbk(v);
G[v].pbk(u);
}
for(int i = 1; i <= n; i ++){
if(!dfn[i])
tarjan(i, i);
}
for(int i = 1; i <= bcnt; i ++){
printf("%d ", i);
for(int j = 0; j < bcc[i].size(); j ++)
printf("%d ", bcc[i][j]);
printf("\n");
}
return 0;
}
tarjan图论算法的更多相关文章
- 图论算法-Tarjan模板 【缩点;割顶;双连通分量】
图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; ...
- [算法模版]Tarjan爷爷的几种图论算法
[算法模版]Tarjan爷爷的几种图论算法 前言 Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会).这里会对这三种算法进行简单介绍. 定义 强连通(strongl ...
- NOIp 图论算法专题总结 (2)
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 树链剖分 https://oi-wiki.org/graph/heavy-lig ...
- LCA问题的ST,tarjan离线算法解法
一 ST算法与LCA 介绍 第一次算法笔记这样的东西,以前学算法只是笔上画画写写,理解了下,刷几道题,其实都没深入理解,以后遇到新的算法要把自己的理解想法写下来,方便日后回顾嘛>=< R ...
- 图论算法-最小费用最大流模板【EK;Dinic】
图论算法-最小费用最大流模板[EK;Dinic] EK模板 const int inf=1000000000; int n,m,s,t; struct node{int v,w,c;}; vector ...
- 图论算法-网络最大流【EK;Dinic】
图论算法-网络最大流模板[EK;Dinic] EK模板 每次找出增广后残量网络中的最小残量增加流量 const int inf=1e9; int n,m,s,t; struct node{int v, ...
- LCA最近公共祖先(Tarjan离线算法)
这篇博客对Tarjan算法的原理和过程模拟的很详细. 转载大佬的博客https://www.cnblogs.com/JVxie/p/4854719.html 第二次更新,之前转载的博客虽然胜在详细,但 ...
- LCA(最近公共祖先)--tarjan离线算法 hdu 2586
HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/ ...
- 最近公共祖先LCA Tarjan 离线算法
[简介] 解决LCA问题的Tarjan算法利用并查集在一次DFS(深度优先遍历)中完成所有询问.换句话说,要所有询问都读入后才开始计算,所以是一种离线的算法. [原理] 先来看这样一个性质:当两个节点 ...
随机推荐
- LiggEasyWinApp-103-Ligg.EasyWinForm:View
首先请在VS里打开下面的文件,我们将对源码分段进行说明: View(视图):一个Function(功能)对应多个View(视图),本框架用View(视图)实现多窗体(MDI)的效果. 一个View(视 ...
- C++调用bat并实现传值
1.设置环境变量,这一类为路径 C++ void bat(const string& sDirC, const string& sDirD) { char Ddir[256]; Ddi ...
- ProjectServer2010升级到ProjectServer2016,Sharepoint2010升级到Sharepoint2016第一章
之后还原 Project Server 2010 数据库和包含 Project Web App 网站数据的 SharePoint 内容数据库,您可以运行数据和 Project Web App 网站集升 ...
- LRC歌词原理和实现高仿Android网易云音乐
大家好,我们是爱学啊,今天给大家带来一篇关于LRC歌词原理和在Android上如何实现歌词逐行滚动的效果,本文来自[Android开发项目实战我的云音乐]课程:逐字滚动下一篇文章讲解. 效果图 相信大 ...
- Ribbon负载均衡及Feign消费者调用服务
微服务调用Ribbon 简介 前面讲了eureka服务注册与发现,但是结合eureka集群的服务调用没讲. 这里的话 就要用到Ribbon,结合eureka,来实现服务的调用: Ribbon是Netf ...
- (转)Ioc控制反转和依赖注入
转载地址:https://zhuanlan.zhihu.com/p/95869440 控制反转控制反转(Inversion of Control,简称IoC),是面向对象编程中的一种设计思想,其作用是 ...
- python怎么连接MySQL(附源码)
一.源码如下: import pymysql from pymysql.cursors import DictCursor # 创建数据库连接 localhost等效于127.0.0.1 conn = ...
- 使用admin的步骤、必知必会13条、单表的双下划线、外键的操作、多对多的操作:
MVC M: model 模型 与数据库交互 V: view 视图 HTML C:controller 控制器 流程 和 业务逻辑 MTV M:model ORM T:template 模板 HTML ...
- TYUT程序设计入门第四讲练习题题解--数论入门
程序设计入门第四讲练习题题解--数论入门 对于新知识点的学习,需要不断地刷题训练,才能有所收获,才能更好地消化知识点. 题组链接: 程序设计入门第四讲练习题--数论 by vjudge 题解: A. ...
- Linux下shell脚本实现mongodb定时自动备份
MongoDB是一个基于分布式文件存储的数据库.由C++语言编写.旨在为WEB应用提供可扩展的高性能数据存储解决方案. MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功 ...