强连通,Tarjan,缩点

在本文中,我们用 \(f(x,y)=1\) 来表示 \(x\) 可以到达点 \(y\),用 \(g(x,y)=1\) 表示 \(f(x,y)=1\)\(f(y,x)=1\)

I、强连通

对于图 \(U\) 上的任意两点 \(x\)\(y\),如果有 \(g(x,y)=1\),那么称 \(x,y\) 是强连通的。

对于图 \(U\) 的子图 \(V\),若 \(V\) 中任意两点 \(x,y\) 都满足 \(g(x,y)=1\),则称图 \(V\) 是一个强连通分量。

II、Tarjan

一、定义

  1. vector <int> v[N] 表示原图。
  2. int dfn[N] 表示 dfs 序中第 \(i\) 个点的时间戳。
  3. int low[N] 表示节点 \(i\) 所处的强连通分量中最小的时间戳。
  4. stack <int> st 表示 dfs 的路径上的节点。
  5. bool is[N] 表示节点 \(i\) 是否处于栈中。
  6. int tim 表示时间戳。

二、具体操作

  1. 找到一个未被访问过的节点 \(x\),将 \(x\) 入栈,更新 \(x\) 的时间戳,且更新:
vis[x] = 1;
low[x] = dfn[x];
is[x] = 1;
st.push(x);
  1. 遍历所有邻接节点 \(y\)
  • \(y\) 未被访问,则继续递归,并更新 low[x] = min(low[x],low[y]);

  • \(y\) 被访问过,且在栈中,则更新 low[x] = min(low[x],dfn[y]);

  • \(y\) 被访问过,但不在栈中,说明 \(y\) 在另一个强连通分量中。

  1. 遍历完成后,如果 low[x] = dfn[x],说明 \(x\) 是一个强连通分量中编号最小的,从栈中弹出所有和 \(x\) 在一个强连通分量里的元素 \(y\),并更新:
low[y] = low[x];

由于我们是按路径遍历的,所以栈剩下的一定不和 \(x\) 在一个强连通分量里。

时间复杂度为 O(n)。

III.缩点

对于每一个强连通分量,它的内部都是联通的,如果内部的点之间没有贡献或贡献容易计算,那么我们可以把它当成一个点来看。

一、定义

只需要在 Tarjan 求强连通分量的情况下,添加:

  1. int num[N]\(i\) 个点的缩点后的编号。
  2. int sum 编号的计数戳。

二、具体步骤

在 Tarjan 求强连通分量的情况下,添加:

  • 对于 \(x\),更新:
sum++,num[x] = sum;
  • 在遍历完成后弹出的元素 \(y\) 更新:
num[y] = num[x];

三、更多的操作:

可以添加:

  • int siz[N] 表示第 \(i\) 个强连通分量(或点)的大小。
  • int in[N] 表示第 \(i\) 个点的入度。
  • int out[N] 表示第 \(i\) 个点的出度。

IIII.例题

  1. 给你一个 \(n\) 个点,\(m\) 条边的有向图,如果第 \(i\) 个点的颜色为 1,那么它相邻的节点的颜色也为 1,问最少将多少个节点的颜色染成 1,才能使最后所有节点颜色为 1。

分析:对于每一个缩点,只要一个节点颜色为 1,那么整个缩点的颜色为 1,缩点的颜色还可以往相邻的缩点传,最终就是要求缩点后有多少个连通块。

//  \\\\ \\ \\ \\ \\ \\ \\        =88888=          // // // // // // ////
//  \\\\ \\ \\ \\ \\ \\          o8888888o            // // // // // ////
//  \\\\ \\ \\ \\ \\             88" . "88               // // // // ////
//  \\\\ \\ \\ \\                (| -_- |)                  // // // ////
//  \\\\ \\ \\                   O\  =  /O                     // // ////
//  \\\\ \\                   ____/`---'\____                     // ////
//  \\\\                    .'  \\|     |//  `.                      ////
//  //==                   /  \\|||  :  |||//  \                     ==\\//  //==                  /  _||||| -:- |||||-  \                    ==\\//  //==                  |   | \\\  -  /// |   |                    ==\\//  //==                  | \_|  ''\---/''  |   |                    ==\\//  //==                  \  .-\__  `-`  ___/-. /                    ==\\//  //==                ___`. .'  /--.--\  `. . ___                  ==\\//  //==             ."" '<  `.___\_<|>_/___.'  >' "".               ==\\//  //==            | | :  `- \`.;`\ _ /`;.`/ - ` : | |              \\\\//  ////            \  \ `-.   \_ __\ /__ _/   .-` /  /              \\\\//  ////      ========`-.____`-.___\_____/___.-`____.-'========      \\\\//  ////                           `=---='                           \\\\//  //// //   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^  \\ \\\\//  //// // //      佛祖保佑      永无BUG      永不修改        \\ \\ \\\\\\//  //// // // // // // || || || || || || || || || || \\ \\ \\ \\ \\ \\\\ #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll, ll> P;
typedef __int128 int128;
#define IOS ios::sync_with_stdio(0);
#define rep(i,x,y,z) for(int i = x;i <= y;i+=z)
#define per(i,y,x,z) for(int i = y;i >= x;i-=z)
#define frin(x) freopen(x,"r",stdin);
#define frout(x) freopen(x,"w",stdout);
const int N = 1e6 + 5;
const int M = 2e3 + 5;
const int K = 18;
const double eps = 1e-6;
const int INF = 0x3f3f3f3f;
const int dx[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const int dy[] = {0, 0, -1, 1, 1, -1, -1, 1};
namespace better_function {inline ll read() {ll s = 0, w = 1;char c = getchar();while (c < '0' || c > '9') {if (c == '-') w = -1;c = getchar();}while (c >= '0' && c <= '9') {s = s * 10 + c - '0';c = getchar();}return s * w;}inline void print(ll x) {if (x < 0) {putchar('-');x = -x;}if (x >= 10) {print(x / 10);}putchar(x % 10 + '0');return;}inline ll pow(ll x, ll y, ll z) {if (z == 0) z = INF;ll ans = 1;while (y) {if (y % 2) {ans *= x;}x *= x;y >>= 1;}return ans;}inline ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}inline ll lcm(ll a, ll b) {return a * b / gcd(a, b);}
}
namespace ex_prime {bool Isprime[N];int Phi[N], Prime[N], prime_num;inline void euler(ll n) {Phi[1] = 1;rep(i, 2, n, 1) {if (Isprime[i] == 0) Prime[++prime_num] = i, Phi[i] = i - 1;rep(j, 1, prime_num, 1) {if (Prime[j] * i > n) break;Isprime[i * Prime[j]] = 1;if (i % Prime[j] == 0) {Phi[i * Prime[j]] = Phi[i] * Prime[j];break;} else Phi[i * Prime[j]] = Phi[i] * Phi[Prime[j]];}}}inline int prime(ll x) {if (!prime_num) euler(N);if (x > prime_num) return -1;return Prime[x];}inline int phi(ll x) {if (!prime_num) euler(N);if (x > N - 5) return -1;return Phi[x];}inline bool isprime(ll x) {if (!prime_num) euler(N);if (x > N - 5) return -1;return Isprime[x];}
}
inline void solve();
int main() {IOS;//frin("");frout("");int T = 1;//cin >> T;while (T--) {solve();}return 0;
}
using namespace better_function;
using namespace ex_prime;
int n,dfn[N],low[N],tim;
bool is[N];
int sum,col[N],in[N];
stack <int> st;
vector <int> v[N];
void dfs_tarjan(int x) {dfn[x] = low[x] = ++tim;st.push(x);is[x] = 1;rep(i,0,(int)v[x].size() - 1,1) {int y = v[x][i];if(!dfn[y]) {dfs_tarjan(y);low[x] = min(low[x],low[y]);}else if(is[y]) {low[x] = min(low[x],dfn[y]);}}if(dfn[x] == low[x]) {int y;sum++;do{y = st.top();st.pop();col[y] = sum;is[y] = 0;}while(y != x);}
}
void Tarjan() {rep(i,1,n,1) {if(!dfn[i]) {dfs_tarjan(i);}}
}
inline void solve() {cin >> n;rep(i,1,n,1) {rep(j,1,n,1) {int x;cin >> x;if(x) v[i].push_back(j);}}Tarjan();rep(i,1,n,1) {rep(j,0,(int)v[i].size() - 1,1) {int y = v[i][j];//	cout << i << ' ' << col[i] << ' ' << y << ' ' << col[y] << endl;if(col[i] != col[y]) {in[col[y]]++;}}}int ans = 0;rep(i,1,sum,1) {if(!in[i]) ans++;}cout << ans;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/923983.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实用指南:K8s日志架构:Sidecar容器实践指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

做网站时量宽度的尺子工具thinkphp做的网站源码

目录结构 全局文件 1.app.json 文件 用来对微信小程序进行全局配置&#xff0c;决定页面文件的路径、窗口表现、设置网络超时时间、设置多 tab 等。文件内容为一个 JSON 对象。 1.1 page用于指定小程序由哪些页面组成&#xff0c;每一项都对应一个页面的 路径&#xff08;含文…

企业网站建设综合实训心得wordpress安装系统

http://home.cnblogs.com/blog/转载于:https://www.cnblogs.com/yanyanhappy/archive/2012/09/07/2675050.html

彩票网站自己可以做吗wordpress加密页面访问

文章目录 一、 Zookeeper常用命令1. zk服务命令2. zk客户端命令 二、HBASE常见运维命令1. 集群启动关闭2. 扩容增加regionserver3. 下线regionserver ing 一、 Zookeeper常用命令 例如&#xff1a;ZOOKEEPER_HOME&#xff1a;/opt/zk/zookeeper 1. zk服务命令 1. 启动ZK服务…

Python方案--交互式VR教育应用开发

Python方案--交互式VR教育应用开发pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&…

纯Qt代码实现onvif协议设备端/onvif设备模拟器/onvif虚拟监控设备/桌面转onvif

一、前言说明 在视频监控系统的开发中,ONVIF(Open Network Video Interface Forum)作为行业标准协议,被广泛应用于设备与平台之间的互联互通。通常我们认为,ONVIF 协议的设备端实现应运行在摄像头等嵌入式下位机上…

高中教做网站的软件表格制作教程 步骤

可能是明月好久没有使用境外服务器挂载境外的云盘缘故吧,今天一个代维客户需要他的Linux服务器挂载谷歌云盘好进行云备份,本来是个很简单的事儿,没想到在rclone连接谷歌云盘的时候卡壳了,可是把明月给难为坏了,搜索到的简体中文教程倒是很多,但没有一个提到这个“坑”,最…

OI 笑传 #13

zatto今天是思维题大手子。 CF2130B 左转这个东西很烦,把它规约掉。 由于是一定要到 \(n\) 的,因此左转之后必须要右转,考虑单位元,也就是左走一格之后往右走一格是怎么个事。也就是多加一倍这两个格子里的数。 考…

*补*““逆元求组合数”(费马小定理

组合数快速求法 #include <bits/stdc++.h> #define ll long long #define MAXN 1010 using namespace std; namespace SHuxinn{ll pri[MAXN];ll ni[MAXN];ll ans1 , ans2;ll pow(ll a , ll b){ll ans = 1 , base…

C# WPF中Binding的 Source属性和ElementName属性有什么区别

好的,这是一个WPF数据绑定中非常核心和常见的问题。Source 和 ElementName 都是用来设置绑定源(即数据的来源)的属性,但它们的应用场景和灵活性有显著区别。 下面通过一个对比表格和详细解释来说明它们的区别。 核…

Typora to Obsidian 迁移助手 (Typora-to-Obsidian-Migration-Helper)

一个交互式的、基于状态机模式的 Python 脚本,旨在帮助用户安全、高效地将 Typora 笔记库迁移至 Obsidian。它将多个繁琐的手动步骤整合为一个自动化的、可控的流程。本脚本基于历史文章中模块程序组合而成,能够实现…

网站怎么做关键词搜索网站建设 无法打开asp

发送报文处理 增加一个功能码映射关系 //功能码映射关系public readonly Dictionary<string, byte> ReadFuncCodes = new Dictionary<string, byte>();<

二七网站建设网站分析与优化

每当MyBatis设置PreparedStatement的参数或从ResultSet中检索值时&#xff0c;都会使用TypeHandler以适合Java类型的方式来检索值。下表描述了默认的TypeHandlers。 自MyBatis 3.4.5版本起&#xff0c;默认支持JSR-310&#xff08;日期和时间API&#xff09;。 Type HandlerJ…

台州网站建设技术支持网站上的3d产品展示怎么做

目录 一、压力的方向(FORCE) 1、为正的情况 2、为负的情况 二、压强的方向(PRESSURE)

深入解析:【APK安全】敏感数据泄漏风险与防御指南

深入解析:【APK安全】敏感数据泄漏风险与防御指南pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas"…

大型网站建设与维护过程学做家常菜的网站有哪些

1、过期删除策略 1.1、介绍 Redis 是可以对 key 设置过期时间的&#xff0c;因此需要有相应的机制将已过期的键值对删除&#xff0c;而做这个工作的就是过期键值删除策略。 每当我们对一个 key 设置了过期时间时&#xff0c;Redis 会把该 key 带上过期时间存储到一个过期字典…

网站设置密码最近韩国电影片

标题&#xff1a;递增三元组 给定三个整数数组 A [A1, A2, … AN], B [B1, B2, … BN], C [C1, C2, … CN]&#xff0c; 请你统计有多少个三元组(i, j, k) 满足&#xff1a; 1 < i, j, k < NAi < Bj < Ck 【输入格式】 第一行包含一个整数N。 第二行包含N个整…

详细介绍:开源 java android app 开发(十七)封库--混淆源码

详细介绍:开源 java android app 开发(十七)封库--混淆源码2025-10-01 15:05 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !impor…

Meta基础设施演进与AI技术革命

本文详细介绍了Meta从传统社交网络基础设施向AI驱动架构的演进历程,涵盖分布式系统构建、GPU集群扩展、自研芯片开发、散热解决方案等关键技术挑战与创新突破。Meta基础设施演进与AI时代 在过去的21年里,Meta从连接美…

完整教程:Spring AI整合聊天模型DeepSeek

完整教程:Spring AI整合聊天模型DeepSeekpre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "…