强连通分量:其实就是个环

割点:把这个点去掉可以使图不连通

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算法求强连通分量割点桥相关推荐

  1. Tarjan 算法思想求强连通分量及求割点模板(超详细图解)

    割点定义 在一个无向图中,如果有一个顶点,删除这个顶点及其相关联的边后,图的连通分量增多,就称该点是割点,该点构成的集合就是割点集合.简单来说就是去掉该点后其所在的连通图不再连通,则该点称为割点. 若 ...

  2. Tarjan算法(求强连通分量与割点)

    Tarjan算法,是以一位计算机界大佬的名字命名的算法,多用于解决LCA,割点,强连通分量等问题,下面是其发明者的简短介绍. Robert Tarjan,计算机科学家,以LCA.强连通分量等算法闻名. ...

  3. 算法提高课-图论-有向图的强连通分量-AcWing 1174. 受欢迎的牛:tarjan算法求强连通分量、tarjan算法板子、强连通图

    文章目录 题目解答 题目来源 题目解答 来源:acwing 分析: 强连通图:给定一张有向图.若对于图中任意两个结点x,y,既存在从x到y的路径,也存在从y到x的路径,则称该有向图是"强连通 ...

  4. 迷宫城堡 HDU - 1269 (塔尖算法求强连通分量)

    为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A房间和B房间,只说明可以 ...

  5. tarjan对有向图的缩点(求强连通分量)

    tarjan对有向图的缩点(求强联通分量) 0x00 tarjan算法简介 tarjan算法是基于DFS的算法,核心在于巧妙的使用访问节点的时间戳 和 栈. tarjan算法可以用于求解: 最近公共祖 ...

  6. Tarjan求强连通分量

    [算法定义] 在有向图中,如果两个顶点至少存在一条路径(可以相互通达),则称两个顶点强连通(strongly connected). 如果有向图G的每两个顶点都强连通,称G是一个强连通图. 非强连通有 ...

  7. 强连通基础与例题(Kosaraju算法与Tarjan算法)

    目录 Kosaraju算法 Tarjan算法 例题 A:HDU-1269 迷宫城堡 B:HDU-2767 Proving Equivalences C:HDU-1827 Summer Holiday ...

  8. hdu 1269(Tarjan求强连通分量)

    这道题目就是求强连通分量... 这里采用的是Tarjan算法:http://m.blog.csdn.net/blog/qq574857122/16361033 AC代码: #include<io ...

  9. hdu 1269 tarjan求强连通分量

    tarjan求强连通分量的裸题复习,可当做模板. 1 #include <stack> 2 #include <cstdio> 3 #include <cstring&g ...

  10. 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 ...

最新文章

  1. 爬虫--pyquery使用
  2. 计算机书籍-老年人编程自学书籍
  3. 机房动力环境监控对消防子系统、UPS不间断电源监控方案
  4. 将R非时间序列的data.frame转变为时序格式
  5. SSIS package 更新 variable
  6. 牛客网【每日一题】4月30日题目精讲 换个角度思考
  7. python来源是什么_python起源?为什么使用python?直至爱上python的五个理由
  8. 成都软件工程师python_为什么每个软件工程师都应该学习Python?
  9. .net pdf转图片_pdf2image类库实现批量pdf转图片
  10. 最全目标检测相关资料整理 (目标检测+数据增强+卷价神经网络+类别不均衡...)
  11. 热门专业学习之关于java的一些知识
  12. 获取roi内的xld_提升ROI是王道,这几种推广获客渠道与形式你还不知道?
  13. linux vi路径配置,Linux 下 Vi 配置文件 .vimrc 文件
  14. 清华操作系统实验lab1
  15. 实现齿轮转动动画CSS3特效
  16. SSD与HDD如何混合组raid并永久挂载硬盘?
  17. [leetcode] 893. Groups of Special-Equivalent Strings
  18. JAVA计算机毕业设计园艺生活网站Mybatis+源码+数据库+lw文档+系统+调试部署
  19. PowerBI中导出数据方法汇总
  20. NSoup Select 示例

热门文章

  1. Google Maps API 中的标注编程
  2. 成都程序员俱乐部通知
  3. 安装MySQL出现 Install/Remove of the Service Denied!
  4. 如何让百度快速收录自己的wordpress网站
  5. 自增字段不连续_MySQL中自增主键不连续之解决方案。(20131109)
  6. 封装系统驱动放哪里啊_MPS做一体化电机驱动方案有三大绝招
  7. java datasource使用_java Datasource,数据库连接池
  8. Mysql之数据库与sql
  9. 大数阶乘 nyoj28
  10. 系统背景描述_【通用博世丨智能广播系统】新都芳华微马公园