Part1:有向图的强连通分量:

一个连通图只有一个联通分量就是自身,非连通图有多个连通分量。

在有向图G中,如果两个顶点vi,vj间(vi>vj)有一条从vi到vj的有向路径,同时还有一条从vj到vi的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。

而有向图G的极大强连通子图S,即添加任意顶点都会导致S失去强连通的属性,则称S为G的强连通分量。

DFS生成树:

对于一棵的dfs生成树,树边可以分为以下4类:

1.树枝边<x,y> x是y的父节点。

2.前向边<x,y> x是y的祖宗节点。

3.后向边<x,y> 返祖边y是x的祖宗节点。

4.横叉边<x,y> x已经被dfs遍历过,但x不是y的一个祖宗节点

根据DFS生成树如何找到强连通分量:

如果结点 u 是某个强连通分量在搜索树中遇到的第一个结点,那么这个强连通分量的其余结点肯定是在搜索树中以 u为根的子树中。结点 u被称为这个强连通分量的根。

反证法:假设有个结点 v在该强连通分量中但是不在以 u为根的子树中,那么 u到 v的路径中肯定有一条离开子树的边。但是这样的边只可能是横叉边或者反祖边,然而这两条边都要求指向的结点已经被访问过了,这就和 u 是第一个访问的结点矛盾了,命题得证。

为了找到强连通分量在搜索树中的第一个节点,我们引入时间戳(timestamp)

Tarjan 算法求强连通分量
在 Tarjan 算法中为每个结点 u维护了以下几个变量:

dfn(u)表示遍历到u时的时间戳;

low(u)表示从u开始遍历到的最小时间戳;

那么如果low[u]==dfn[u],u就是我们所求的强连通分量在搜索树中的第一个结点。

tarjan 缩点

找到所有强连通分量后,遍历i的所有邻点,如果i和j不在同一连通分支,那么在这两个联通分支之间连一条有向边就能缩点,而且缩点后的图时DAG(拓扑图)。

参考视频:

[算法]轻松掌握tarjan强连通分量_哔哩哔哩_bilibili

1174. 受欢迎的牛

每一头牛的愿望就是变成一头最受欢迎的牛。

现在有 N 头牛,编号从 1 到 N,给你 M 对整数(A,B),表示牛 A 认为牛 B 受欢迎。

这种关系是具有传递性的,如果 A 认为 B 受欢迎,B 认为 C 受欢迎,那么牛 A 也认为牛 CC 受欢迎。

你的任务是求出有多少头牛被除自己之外的所有牛认为是受欢迎的。

输入格式

第一行两个数 N,M;

接下来 M 行,每行两个数 A,B,意思是 A 认为 B 是受欢迎的(给出的信息有可能重复,即有可能出现多个 A,B)。

输出格式

输出被除自己之外的所有牛认为是受欢迎的牛的数量。

数据范围

1≤N≤104,
1≤M≤5×104

输入样例:

3 3
1 2
2 1
2 3

输出样例:

1

样例解释

只有第三头牛被除自己之外的所有牛认为是受欢迎的。

思路:将受欢迎看成一种关系,牛看成点,x欢迎y就是从x->y 有一条有向边,假设s、t是一部分被所有牛认为是受欢迎的牛,(s与其他任何点联通,t也与其他任何点联通)同时s、t互相认为对方是受欢迎(互相连通)的因此s、t是强联通的,这就说明被所有牛都受欢迎的牛构成的图是原图的一个强连通分量,利用tarjan算法求出原图的所有强连通分量;当一个强连通分量的出度为0,则该强连通分量中的所有点都被其他强连通分量的牛欢迎。但假如存在两及以上个出度=0的牛(强连通分量) 则必然有一头牛(强连通分量)不被所有牛欢迎,这就说明满足条件的牛构成的图是原图的唯一的一个强连通分量。

code:

#include<bits/stdc++.h>
using namespace std;
const int N =5e4+10;
int e[N],h[N],ne[N],idx;
int dfn[N],timestamp;
int low[N],id[N],scc_cnt;
bool in_stk[N];
int stk[N],top;
int sz[N];
int dout[N];
int n,m;
void add(int a,int b ){e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
void tarjan(int u){dfn[u]=low[u]=++timestamp;stk[++top]=u;in_stk[u]=true;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(!dfn[j]){tarjan(j);low[u]=min(low[u],low[j]);}else if(in_stk[j]){low[u]=min(low[u],dfn[j]);}}if(low[u]==dfn[u]){++scc_cnt;int y;do{y=stk[top--];in_stk[y]=false;id[y]=scc_cnt;sz[scc_cnt]++;}while(y!=u);}
}
signed main(){cin>>n>>m;memset(h,-1,sizeof h);while(m--){int a,b;cin>>a>>b;add(a,b);}for(int i=1;i<=n;i++){if(!dfn[i]){tarjan(i);}}for(int i=1;i<=n;i++){for(int j=h[i];~j;j=ne[j]){int k=e[j];int a=id[i],b=id[k];if(a!=b){dout[a]++;}}}int zeros=0,sum=0;for(int i=1;i<=scc_cnt;i++){if(!dout[i]){zeros++;sum+=sz[i];if(zeros>1){sum=0;break;}}}cout<<sum<<endl;return 0;
}

tarjan算法求解强连通分量问题相关推荐

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

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

  2. tarjan算法总结 (强连通分量+缩点+割点),看这一篇就够了~

    文章目录 一.tarjan求强连通分量 1:算法流程 2:模板 二.tarjan缩点 1:相关定义 2:算法流程 三.tarjan求割点.桥 1.什么是割点 2.割点怎么求? 3.割点tarjan模板 ...

  3. tarjan算法(强连通分量与割点)

    tarjan算法可以求有向图的割点割边强连通分量(还有一些奇奇怪怪的操作) 我只会割点和强连通分量,割边(和缩点)以后可能会加,如果是来看割边的话,现在跑还来得及.. (先来一张有向图叭) 用这张图, ...

  4. POJ2186——并查集+Tarjan算法求强连通分量

    算法讨论:这题陷阱比较多.首先,被所有牛欢迎,这说明所有的牛都要在一个连通图中,也就是将所给的边看成无向边的时候,所有点要在一个连通图中.这个我们用并查集来实现就可以了.强连通分量的求法就很简单了,正 ...

  5. 解题报告:luogu P2341 受欢迎的牛(Tarjan算法,强连通分量判定,缩点,模板)

    题目链接:洛谷 受欢迎的牛 基本上算是一道模板题 根据题意,如果有环,意味着这个环里的牛都互相喜欢 我们可以先求出环,然后把每一个环都看作一个点,这样整个图就变成了一个DAG(有向无环图) 看有几个点 ...

  6. 算法竞赛——强连通分量

    强连通分量 强连通的定义是:有向图 G 强连通是指,G 中任意两个结点连通. 强连通分量(Strongly Connected Components,SCC)的定义是:极大的强连通子图也可以说,在强连 ...

  7. Tarjan算法求解桥和边双连通分量(附POJ 3352 Road Construction解题报告)

    http://blog.csdn.net/geniusluzh/article/details/6619575 在说Tarjan算法解决桥和边双连通分量问题之前我们先来回顾一下Tarjan算法是如何求 ...

  8. 双连通图强连通图概念解释以及tarjan算法求解该类问题总结

    最近看了看类的相关题,感觉简单的题过于模板,但是对于难题的转化,如果对与这方面的概念不清楚,很难写,故总结一下. PS:博客里部分内容会和离散数学中的图论知识有联系,如果没有了解过相关知识可能比较难理 ...

  9. Targan 算法[有向图强连通分量]

    [有向图强连通分量] 在有向图G中,如果两个顶点间至少存在一条路径,称两个顶点强连通(stronglyconnected).如果有向图G的每两个顶点都强连通,称G是一个强连通图.非强连通图有向图的极大 ...

最新文章

  1. P1449 后缀表达式
  2. Windows Forms高级界面组件-快捷菜单
  3. android 如何适配屏幕
  4. MySQL查询的性能优化
  5. 为什么 SAP Spartacus 不手动导入 UserAccountModule,就看不到 LoginForm?
  6. JAVA遍历map元素
  7. 江苏省计算机二级c语言备考,江苏省计算机二级C语言考试备考指南
  8. 查看 java opts,如何在命令提示符中检查JAVA_OPTS值?
  9. linux中wine文件夹在哪,linux下wine的使用
  10. WSDM2019|门限注意力自编码在内容感知推荐中的应用(已开源)
  11. python计算圆的周长_Python计算圆周长和面积
  12. 短信通知接口json报文开发设计总结
  13. mfc 中文乱码转换为正常中文_中文编码转换
  14. 数据分析 VS 算法模型,如何高效分工合作?
  15. 告诉你什么是挖洞最清奇的脑回路
  16. 正则表达式 - Python 正则表达式 学习笔记 最全整理
  17. win11怎么共享文件夹 Windows11共享文件夹的设置方法
  18. C2B的未来:大数据定制
  19. idea调整代码标签编辑器标签editor tabs的横排和竖排
  20. 2022深圳杯A题论文

热门文章

  1. Sparql与sql的比较
  2. CouchDB与CouchBase的比较
  3. 微信小程序swiper上下滑动卡顿
  4. C# 及excel中【总体方差】、【样本方差】的计算公式
  5. 实战派来了!聊聊百度智能运维的“前世今生” | 技术沙龙
  6. key 、primary key 、unique key 与index区别
  7. python+sklearn实现决策树模型
  8. 四个有意义的哲理故事
  9. 今天面完了聚成网络的php研发,面经一枚,为自己攒人品。
  10. Date int java_java.util.Calendar.set(int year, int month, int date)方法实例