强连通分量-tarjan算法缩点

news/2025/2/12 8:00:34/

 一. 什么是强连通分量?

强连通分量:在有向图G中,如果两个顶点u,v间(u->v)有一条从u到v的有向路径,同时还有一条从v到u的有向路径,则称两个顶点强连通(strongly connected)。如果有向图G的每两个顶点都强连通,称G是一个强连通图。有向图的极大强连通子图,称为强连通分量。
简单点说就是:如果一个有向图中,存在一条回路,所有的结点至少被经过一次,这样的图为强连通图。
在强连图图的基础上加入一些点和路径,使得当前的图不在强连通,称原来的强连通的部分为强连通分量。

二. 强连通分量有什么用途呢?

在图论中,我们可以利用强连通分量进行缩点,从而可以减少很多不必要的操作,降低程序的时间复杂度。

三. tarjan求强连通分量

在讲tarjan算法之前我们先来讲几个概念:
1.树枝边:x是y的父节点,那么x到y的边称为树枝边。
2.前向边:x是y的祖先节点,那么x到y的边称为前向边。
3.后向边:y是x的的祖先节点,那么y到x的边称为后向边。
4.横叉边:x是y的祖先节点,并且y能到达已经搜过的点,那么这条边被称为横叉边。

根据定义可以得知:树枝边也是一个特殊的前向边。
我们在深度优先搜索的时候是从上向下搜的,所以画图看一下(自己画的图,可能有点丑 )
3951ea4ea6d74e628cfd978653bc9484.png#pic_center
知道这些定义后,我们来看一下tarjan算法是如何求强连通分量的。
在这里,我们引入一个时间戳的概念:在深度优先搜索的时候,当前结点x是第几个被搜索到的,记为df[x]。
对于每一个结点,我们定义两个时间戳。
df[x]:x结点是第几个被搜索到的。
low[x]:从x结点开始搜索,能搜索到深度最低的结点是什么,也就是能搜索到时间戳最小的结点。
在搜索的时候我们该如何判断是一个新的强连通分量呢?
如果一个图是强连通的话,那么必然会搜完他图中的所有结点,并且从任意一个结点到达另一个结点,所以强连通分量中的点都可以遍历到时间戳更小的点。
所以我们可以发现,如果一个结点的df[]==low[]的话,那么说明这个结点是不能搜到比自己的时间戳更小的点了。说明什么呢?说明该节点就是一个强连通分量的最高点,也就是一个新的强连通分量。

下面放入一个题(受欢迎的牛):

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

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

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

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

输入格式
第一行两个数 N,M;

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

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

数据范围
1≤N≤10^4,
1≤M≤5×10^4
输入样例:
3 3
1 2
2 1
2 3
输出样例:
1
样例解释
只有第三头牛被除自己之外的所有牛认为是受欢迎的。

这题乍一看是传递闭包,第一时间会想到Floyd,但是看了数据范围之后发现传递闭包会超时,所以Floyd是不可行的。

我们用强连通分量来做。
题意:a->b且b->c,则a->c

要求的是有多少头牛被除自己之外的所有牛认为是受欢迎的(受欢迎的牛可以被其他的牛走到)。

总结:当一个强连通的出度为0,则该强连通分量中的所有点都被其他强连通分量的牛欢迎,但假如存在两及以上个出度=0的牛(强连通分量) 则必然有一头牛(强连通分量)不被所有牛欢迎。

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;const int N=1e4+10,M=5*N;int h[N],e[M],ne[M],idx;  //邻接表
int id[N];   //id[x]:x结点属于第几个强连通分量
int cnt,times;  //cnt:强连通分量的个数,times:时间戳
int n,m;
bool st[N];  //st[x]:x结点是否在栈中
int df[N],low[N];  //df[x]:x结点第一次被搜索到的时间戳,low[x]:x结点能遍历到最高的点
int sizes[N];  //sizes[x]:第x强连通分量中点的个数
int stack[N],top;  //这里我们用数组模拟栈
int dout[N];  //dout[x]:第x个强连通分量的出度void add(int a,int b){e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}void tarjan(int u){//当前点的时间戳df[u]=low[u]=++times;//把u点入栈stack[++top]=u;st[u]=true;//遍历u结点能到的点for(int i=h[u];i!=-1;i=ne[i]){int j=e[i];if(!df[j]){  //如果没有遍历过,那么就遍历它tarjan(j);low[u]=min(low[u],low[j]);}else if(st[j]) low[u]=min(low[u],low[j]);  //如果在栈中}//找到一个强连通分量if(df[u]==low[u]){cnt++;int t=stack[top--];id[t]=cnt;st[t]=false;sizes[cnt]++;while(t!=u){t=stack[top--];id[t]=cnt;st[t]=false;sizes[cnt]++;}}
}int main(){scanf("%d%d",&n,&m);memset(h,-1,sizeof h);while(m--){int a,b;scanf("%d%d",&a,&b);add(a,b);}for(int i=1;i<=n;i++){if(!df[i]){tarjan(i);}}for(int i=1;i<=n;i++){for(int j=h[i];j!=-1;j=ne[j]){int t=e[j];int a=id[i],b=id[t];  //a:i结点所在的强连通分量,b:t结点所在的强连通分量if(a!=b) dout[a]++;  //因为是a->b,所以a的出度++}}int zero=0;  //出度为0点的个数int sum=0;for(int i=1;i<=cnt;i++){if(!dout[i]){sum+=sizes[i];zero++;}}if(zero>1) printf("%d",0);else printf("%d",sum);return 0;
}


http://www.ppmy.cn/news/229786.html

相关文章

《设计模式》之状态模式

文章目录 1、定义2、动机3、类结构4、优点5、总结6、代码实现(C) 1、定义 允许一个对象在其内部改变时改变它的行为&#xff0c;从而使对象看起来改变了其行为。 2、动机 某些对象的状态如果改变&#xff0c;其行为也会随之而发生改变。比如文档的只读状态和读写状态的行为可…

主机电源全是黑线怎么短接_台式电脑电源高手维修,短接绿黑线风扇转一下就停。...

展开全部 可以用万用表检测5VSB有无输出确定电源是否损坏。 1、5VSB无输出。 此故障制定方法为&#xff1a;将电源从主机e69da5e887aa62616964757a686964616f31333431346362中拆下&#xff0c;接好主机电源交流输入线&#xff0c;用万用表测量电源输出到主板的20芯插头中的紫色…

台式机进入bios后显示器无法显示

问题 huntkey&#xff08;航嘉&#xff09;主机&#xff0c;使用VGA接口外接AOC显示器&#xff0c;开机长按F2&#xff0c;能进入bios&#xff0c;但是显示器黑频无法显示内容&#xff08;造成没有进入bios的错觉&#xff09;。在该主机安装ubuntu18.04后&#xff0c;再转用VG…

建模 渲染 计算机配置,设计师专用电脑 8000元i5-7500独显专业渲染建模电脑配置推荐...

鉴于硬件都早已更新换代&#xff0c;8000的预算如果是买老平台显然是不值的。今天脚本之家的小编主要面向2017年建模渲染专业需求用户推荐一套新平台设计师专用电脑配置方案&#xff0c;以下是具体的配置单。 2017年设计师专用电脑 8000元i5-7500独显专业渲染建模配置推荐 配件…

个人虚拟化集群搭建教程

一、写在前面 本教程最重要还是在建设理念与思路&#xff0c;部分步骤中&#xff0c;因网上可轻松查到的资料&#xff0c;故会省略不详谈。实际搭建过程中&#xff0c;几乎每个步骤均有多重选择&#xff0c;笔者会适当的描述这些选择项。本文着重讲解利用家用组装机pfsense软路…

go语言学习——8

文章目录 文件操作打开文件文件读取写文件判读文件或文件夹是否存在拷贝文件统计文件字符命令行参数flag包解析命令行参数 文件操作 os.File封装所有文件相关操作&#xff0c;File是一个结构体 打开文件 package mainimport ("fmt""os" )func main() {file…

目前市场上配置独立显卡的计算机是,2021上半年主流中高低配置推荐(大部分支持win7系统)...

2021年市场比较混乱&#xff0c;虽然b560主板和11代酷睿cpu都己经发布了&#xff0c;但2021年上半年装机主流还是以b460和10代cpu为主&#xff0c;今天电脑系统城小编就给大家分享关于2021上半年主流中低高端配置清单及参考价格给大家&#xff0c;价格主要是参考&#xff0c;具…

图片处理+高速计算机配置,谁能给我推荐个专业处理图片的计算机配置么

谁能给我推荐个专业处理图片的计算机配置么 來源:互聯網 2009-09-07 05:01:42 評論 分類: 電腦/網絡 問題描述: 价钱在5000-6000之间。 參考答案: CPU 64位Pentium 4 630 (散) | 1,030.00 风扇 Tt火星9 | 95.00 主板 升技 IL8 | 720.00 显卡 迪兰恒进 X1600PRO 加强版 | 599.…