tarjan算法可以求有向图的割点割边强连通分量(还有一些奇奇怪怪的操作)

我只会割点和强连通分量,割边(和缩点)以后可能会加,如果是来看割边的话,现在跑还来得及。。

(先来一张有向图叭)

用这张图,我们来解释一些东西:

设在有向图G中,GG为其子图,u,v分别是G中的节点。

强连通:如果u可以到达v,v也可以到达u,那么u,v强连通。(比如2可以到达9,9可以通过9—10—3—2到达2)

强连通图:若G内各点都强连通,就说G是强连通图。

强联通分量:若GG是强连通图,就说它是G的强连通分量。

割点:设割去点u,G断成了多个图,就说u是G的割点。(如1)

所有的tarjan算法都要用到两个数组:

dfn[]:节点的dfs序;

low[]:该节点所在强连通分量中最小的dfn值,可以理解为团队主。

tarjan如何求强连通分量

首先要维护一个栈,来记录我们找过了哪些点。

然后遍历u的儿子

设v是u的子节点。

如果v没有走过,那么先遍历v的儿子

若v的团队主比u的团队主更高级(low[v]<low[u])显然,u要顺从v的团队主

否则u不变。

如果v已经处理过了在栈里了

若v比u更高级(dfn[v]<low[u]),显然,u要顺从v

否则u不变,坐等v加入团队。

这一部分的代码:

inline void tarjan(int x){dfn[x]=low[x]=++num;//dfs序 st[++top]=x;v[x]=true;//入栈,v[x]标记x在栈内 for(register int i=head[x];i;i=e[i].nxt){if(!dfn[e[i].y]){tarjan(e[i].y);low[x]=min(low[x],low[e[i].y]);}else if(v[e[i].y])low[x]=min(low[x],dfn[e[i].y]);}

当考虑完团队划分整合之后,我们如何确定有几个团队呢

如果dfn[x]==low[x],显然,x就是某个团队的团队主

此时我们需要++cnt(cnt代表目前团队编号),然后将x之后的数全部弹出栈,压入事先准备好的vector中(怎么觉得有点像做菜)。因为在x之后的点都是从x出发遍历到的,这些点之中没有可以改变low[x]的,显然他们都归顺于x。

这一部分的代码:

if(dfn[x]==low[x]){cnt++;int y;do{y=st[top--];v[y]=false;scc[cnt].push_back(y);}while(x!=y);
}

讲完了算法,就可以愉快的来一道板子题了

牛的舞会

这个。。裸的掉牙了。

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
#include<vector>
#define maxn 10005
#define maxm 50005
using namespace std;
int n,m,head[maxn],tot;
int dfn[maxn],low[maxn],num,st[maxn],ans,top,cnt;
bool v[maxn];
struct node{int y,nxt;
}e[maxm];
inline void ad(int x,int y){e[++tot].y=y;e[tot].nxt=head[x];head[x]=tot;
}
vector<int> scc[maxn];
inline void tarjan(int x){dfn[x]=low[x]=++num;//dfs序 st[++top]=x;v[x]=true;//入栈,v[x]标记x在栈内 for(register int i=head[x];i;i=e[i].nxt){if(!dfn[e[i].y]){tarjan(e[i].y);low[x]=min(low[x],low[e[i].y]);}else if(v[e[i].y])low[x]=min(low[x],dfn[e[i].y]);}if(dfn[x]==low[x]){cnt++;int y;do{y=st[top--];v[y]=false;scc[cnt].push_back(y);}while(x!=y);}
}
int main(){scanf("%d%d",&n,&m);int x,y;for(register int i=1;i<=m;i++){scanf("%d%d",&x,&y);ad(x,y);}for(register int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}for(register int i=1;i<=cnt;i++){if(scc[i].size()>1)++ans;}printf("%d",ans);
}

tarjan如何求割点

(呜哇总算写完前半部分啦)

如果一个点是根节点,有多个子树,它肯定是个割点。

如果一个点不是根节点,它存在一个子树,无法连接更高级的团队主,那么这个点就是割点。

(可以这样想,割掉以后那棵子树无法和其他点连接,必然会产生新的块)

板子题

代码

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#define maxn 100005
#define maxm 100005
using namespace std;
int n,m;
int head[maxn],tot,root;
int dfn[maxn],low[maxn],num,ans;
bool cut[maxn];struct node{int y,nxt;
}e[maxn<<1];inline void ad(int x,int y){e[++tot].y=y;e[tot].nxt=head[x];head[x]=tot;
}inline void tarjan(int x){dfn[x]=low[x]=++num;int flag=0;for(register int i=head[x];i;i=e[i].nxt){int y=e[i].y;if(!dfn[y]){tarjan(y);low[x]=min(low[x],low[y]);if(dfn[x]<=low[y]){flag++;if(x!=root||flag>1)cut[x]=true; }}else{low[x]=min(low[x],dfn[y]);}}
}
int main(){scanf("%d%d",&n,&m);int x,y;for(register int i=1;i<=m;i++){scanf("%d%d",&x,&y);ad(x,y);ad(y,x);}for(register int i=1;i<=n;i++){if(!dfn[i])root=i,tarjan(i);}for(register int i=1;i<=n;i++)if(cut[i])++ans;printf("%d\n",ans);for(register int i=1;i<=n;i++){if(cut[i])printf("%d ",i);}return 0;
}

终于写完了qwq

flag插地:这周学会割边和缩点!

谢谢你可以看到这里呀

希望对你有所帮助

有写的不好或者不对的地方要及时指出来哦qwq

tarjan算法(强连通分量与割点)相关推荐

  1. nyist120 校园网络 (Tarjan算法 / 强连通分量)

    校园网络(nyist 120) 解题思路请看代码块中的注释~ import java.util.Scanner; import java.util.Stack; import java.util.Ve ...

  2. `Computer-Algorithm` Tarjan算法,强连通分量SCC,PBCC割点,EBCC割边/桥

    Contents EBCC 例题 PBCC 涉及割点/PBCC时的解决思路 例题 SCC 过去分析 例题 EBCC Some properties of the algorithm: + for a ...

  3. Tarjan有向图强连通分量

    Tarjan有向图强连通分量 本文仅供娱乐,不喜勿喷 一.强连通分量 有向图强连通分量:在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi ...

  4. hdu 1269 tarjan求强连通分量

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

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

  6. 洛谷 P2921 在农场万圣节Trick or Treat on the Farm (tarjan求强连通分量)

    洛谷 P2921 在农场万圣节Trick or Treat on the Farm (tarjan求强连通分量) 题目描述 每年,在威斯康星州,奶牛们都会穿上衣服,收集农夫约翰在N(1<=N&l ...

  7. tarjan算法求无向图的割点和桥

    tarjan算法求无向图的割点与桥 一篇tarjan算法求割点与桥的完整的解释,写的真的好认真 以下代码来自kuangbin的模板 4.5 图的割点.桥和双连通分支的基本概念 [点连通度与边连通度] ...

  8. 超详细Tarjan算法总结,求强连通分量,割点,割边,有重边的割边

    Tarjan是一个人,他一身中发明了很多算法,就这几个算法最为出名. 1.求有向图的强连通分量,那么什么是强连通分量呢,就是一个顶点集合,任意两个顶点间都可以互相到达.一个顶点也是强联通分量如果图中任 ...

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

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

最新文章

  1. 从起源到具体算法,这篇深度学习综述论文送给你
  2. 关于java数据库章节connection连接不成功的时候!!!
  3. html设置box设置长度自适应,CSS实现宽度自适应宽高16:9的矩形的示例
  4. StringBuffer、StringBuilder、ArrayList、Vector、HashMap、HashTable 的扩容机制
  5. Java中的goto实现
  6. 秒过,度目智慧通行让常态化防疫更高效
  7. php大文件上传php.ini配置
  8. 小bat大装逼(▼へ▼メ)
  9. R语言实战学习笔记-高级数据管理
  10. “阿法狗”之父:关于围棋,人类3000年来犯了一个错
  11. 麒麟信安总裁刘文清:携手 openEuler,共推操作系统产业新发展
  12. Moneybookers API支付方式开发 步骤
  13. 在这个“未来工厂”里, 人类仅凭脑电波控制机器
  14. 网页版VIP邮箱有什么宝藏功能?网页邮箱官网注册入口有哪些?
  15. 云班课计算机基础知识答案,云班课上的作业
  16. 弘辽科技:淘宝卖家修改标题的注意事项有哪些?如何预防被降权?
  17. 仿Mac程序坞放大动画
  18. DC-DC电源模块的九个主要性能指标和作用
  19. linux下安装ab压力测试工具及ab命令详解
  20. 交通大学c语言作业,交通大学C语言第二次作业说课讲解.docx

热门文章

  1. 一些想说的话,无关技术
  2. 古诗中古体诗和格律诗的区别
  3. idea用git更新代码,本地被覆盖了怎么办?
  4. seldom 实战技巧
  5. java语言动画模拟_java swing动画模拟太阳系行星运行动画特效
  6. 一文带你直观感受,BPM管理系统如何在低代码平台实现搭建
  7. 关于Pytorch中双向LSTM的输出表示问题
  8. Spark GraphX 中的PageRank算法、pregel函数、航班飞行网图分析
  9. 软件项目上线检查项目
  10. golang json数据解析错误情况