算法笔记:tarjan算法求强连通分量割点桥
强连通分量:其实就是个环
割点:把这个点去掉可以使图不连通
tarjan算法求强连通分量的思路:在dfs过程中有两个数组 low 和dfn 分别代表dfs中被搜索到的次序,以u为根的子树中的最小dfn。对于每一个点,如果它的dfn[u]==low[u]说明通过一条路径走回了自己,因为往后搜索的过程中dfn是在递增的,只有通过一个环走回去才可能使这两个值相等,所以就可以把这个环缩成点
if(low[u]==dfn[u]){t++;//连通分量的标号 do{color[z[k]]=t; //属于这个连通分量 cnt[t]++; //记录这个环中有多少个点vis[z[k]]=0; k--; //出栈 }while(u!=z[k+1]);}
用栈来记录子树
对于每一个新点进行初始化
加入栈中
并记录这个点在栈中
dfn[u]=low[u]=++tot;z[++k]=u;//入栈 vis[u]=1;for(int i=0;i<e[u].size();i++){if(!dfn[e[u][i]]){tarjan(e[u][i]);low[u]=min(low[u],low[e[u][i]]);}else if(vis[e[u][i]]){low[u]=min(low[u],dfn[e[u][i]]);}}
luogu P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
int n,m;
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],du[maxn],t,k,tot;
//dfn 深度优先搜索遍历时结点u被搜索的次序
//low 以u为根的子树的最小dfn
//z 数组模拟栈
//color 记录属于哪个连通分量
//cnt 记录每个连通分量里的元素个数
//du 缩点后 每个点的出度
vector<int>e[maxm];
void tarjan(int u){dfn[u]=low[u]=++tot;z[++k]=u;//入栈 vis[u]=1;for(int i=0;i<e[u].size();i++){if(!dfn[e[u][i]]){tarjan(e[u][i]);low[u]=min(low[u],low[e[u][i]]);}else if(vis[e[u][i]]){low[u]=min(low[u],dfn[e[u][i]]);}}if(low[u]==dfn[u]){t++;//连通分量的标号 do{color[z[k]]=t; //属于这个连通分量 cnt[t]++; //记录这个环中有多少个点vis[z[k]]=0; k--; //出栈 }while(u!=z[k+1]);}
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(int i=1;i<=n;i++){for(int j=0;j<e[i].size();j++){if(color[i]!=color[e[i][j]])du[color[i]]++;}}int ans=0;for(int i=1;i<=t;i++){if(du[i]==0){if(ans){cout<<"0";return 0;}ans=i;}}cout<<cnt[ans];return 0;
}
割点的思想跟强连通分量非常相似,判断任意一个点的儿子是否能走到自己的父亲,如果不能,这个点就是割点 即 low[v]>=dfn[u],还有一种可能,根节点有两个以上的儿子,直接就是割点
luogu P3388 【模板】割点(割顶)
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+5,maxm=2e5+5;
int n,m;
bool cut[maxn];
int dfn[maxn],low[maxn],vis[maxn],z[maxn],color[maxn],cnt[maxn],du[maxn],t,k,tot;
vector<int>e[maxm];
void tarjan(int u,int root){//root代表此树的根 int child=0;dfn[u]=low[u]=++tot;for(int i=0;i<e[u].size();i++){int v=e[u][i];if(!dfn[v]){tarjan(v,root);low[u]=min(low[u],low[v]);if(low[v]>=dfn[u]&&u!=root)cut[u]=true;if(u==root)child++;}low[u]=min(low[u],dfn[v]);}if(u==root&&child>=2){cut[root]=true;}
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);e[u].push_back(v);e[v].push_back(u);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i,i);}int ans=0;for(int i=1;i<=n;i++){if(cut[i])ans++;}cout<<ans<<endl;for(int i=1;i<=n;i++){if(cut[i])cout<<i<<" ";}return 0;
}
真正的正确版本tarjan求桥
核心代码
cnt初始化为1
struct edge{int u,v,w,nex;
}e[maxm];
inline void add(int u,int v,int w){e[++cnt].nex=head[u];e[cnt].v=v;e[cnt].u=u;e[cnt].w=w;head[u]=cnt;
}
void tarjan(int u,int root){dfn[u]=low[u]=++tot;for(int i=head[u];i;i=e[i].nex){int v=e[i].v;if(!dfn[v]){tarjan(v,i);low[u]=min(low[u],low[v]);if(low[v]>dfn[u]){qiao[i]=1;}}else if(i!=(root^1))low[u]=min(low[u],dfn[v]);}return;
}
算法笔记:tarjan算法求强连通分量割点桥相关推荐
- Tarjan 算法思想求强连通分量及求割点模板(超详细图解)
割点定义 在一个无向图中,如果有一个顶点,删除这个顶点及其相关联的边后,图的连通分量增多,就称该点是割点,该点构成的集合就是割点集合.简单来说就是去掉该点后其所在的连通图不再连通,则该点称为割点. 若 ...
- Tarjan算法(求强连通分量与割点)
Tarjan算法,是以一位计算机界大佬的名字命名的算法,多用于解决LCA,割点,强连通分量等问题,下面是其发明者的简短介绍. Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名. ...
- 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图
文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 强连通图:给定一张有向图.若对于图中任意两个结点x,y,既存在从x到y的路径,也存在从y到x的路径,则称该有向图是"强连通 ...
- 迷宫城堡 HDU - 1269 (塔尖算法求强连通分量)
为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以 ...
- tarjan对有向图的缩点(求强连通分量)
tarjan对有向图的缩点(求强联通分量) 0x00 tarjan算法简介 tarjan算法是基于DFS的算法,核心在于巧妙的使用访问节点的时间戳 和 栈. tarjan算法可以用于求解: 最近公共祖 ...
- Tarjan求强连通分量
[算法定义] 在有向图中,如果两个顶点至少存在一条路径(可以相互通达),则称两个顶点强连通(strongly connected). 如果有向图G的每两个顶点都强连通,称G是一个强连通图. 非强连通有 ...
- 强连通基础与例题(Kosaraju算法与Tarjan算法)
目录 Kosaraju算法 Tarjan算法 例题 A:HDU-1269 迷宫城堡 B:HDU-2767 Proving Equivalences C:HDU-1827 Summer Holiday ...
- hdu 1269(Tarjan求强连通分量)
这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...
- hdu 1269 tarjan求强连通分量
tarjan求强连通分量的裸题复习,可当做模板. 1 #include <stack> 2 #include <cstdio> 3 #include <cstring&g ...
- The King’s Problem(tarjan求强连通分量缩点+匈牙利求有向无环图的最小路径覆盖)
Link:http://acm.hdu.edu.cn/showproblem.php?pid=3861 The King's Problem Time Limit: 2000/1000 MS (Jav ...
最新文章
- 爬虫--pyquery使用
- 计算机书籍-老年人编程自学书籍
- 机房动力环境监控对消防子系统、UPS不间断电源监控方案
- 将R非时间序列的data.frame转变为时序格式
- SSIS package 更新 variable
- 牛客网【每日一题】4月30日题目精讲 换个角度思考
- python来源是什么_python起源?为什么使用python?直至爱上python的五个理由
- 成都软件工程师python_为什么每个软件工程师都应该学习Python?
- .net pdf转图片_pdf2image类库实现批量pdf转图片
- 最全目标检测相关资料整理 (目标检测+数据增强+卷价神经网络+类别不均衡...)
- 热门专业学习之关于java的一些知识
- 获取roi内的xld_提升ROI是王道,这几种推广获客渠道与形式你还不知道?
- linux vi路径配置,Linux 下 Vi 配置文件 .vimrc 文件
- 清华操作系统实验lab1
- 实现齿轮转动动画CSS3特效
- SSD与HDD如何混合组raid并永久挂载硬盘?
- [leetcode] 893. Groups of Special-Equivalent Strings
- JAVA计算机毕业设计园艺生活网站Mybatis+源码+数据库+lw文档+系统+调试部署
- PowerBI中导出数据方法汇总
- NSoup Select 示例
热门文章
- Google Maps API 中的标注编程
- 成都程序员俱乐部通知
- 安装MySQL出现 Install/Remove of the Service Denied!
- 如何让百度快速收录自己的wordpress网站
- 自增字段不连续_MySQL中自增主键不连续之解决方案。(20131109)
- 封装系统驱动放哪里啊_MPS做一体化电机驱动方案有三大绝招
- java datasource使用_java Datasource,数据库连接池
- Mysql之数据库与sql
- 大数阶乘 nyoj28
- 系统背景描述_【通用博世丨智能广播系统】新都芳华微马公园