tarjan强连通分量
连通 Tarjan 分量
2023-09-14 09:06:47 时间
dfs维护两个数组
一个是dfs序,另一个是
u
u
u的子树中能够回溯到的最早的已经在栈中的节点
至于low[u] = min(low[u], dfsn[v]);能不能替换为low[u] = min(low[u], low[v]);
视频里的答案是可以,但是为了和其他代码统一,建议不换
而其他网站说不可以,例如wiki和geeksforgeeks
#include<cstdio>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int N = 1e4 + 5;
vector<int> edge[N];
int dfsn[N], tot;//dfs序
int low[N];
stack<int> s;
bool in_stack[N];//是否在栈里
int scc[N], sc;//节点i所在scc编号
int sz[N];//强连通分量i的大小
void tarjan(int u) {
low[u] = dfsn[u] = ++tot;
s.push(u);
in_stack[u] = true;
for (int i = 0; i < edge[u].size(); ++i) {
int v = edge[u][i];
if (!dfsn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (in_stack[v]) {
low[u] = min(low[u], dfsn[v]);
}
}
if (dfsn[u] == low[u]) {
++sc;
while (s.top() != u) {
scc[s.top()] = sc;
++sz[sc];
in_stack[s.top()] = false;
s.pop();
}
scc[u] = sc;
++sz[sc];
in_stack[u] = false;
s.pop();
}
}
int main() {
int n, m, a, b, ans = 0;
scanf("%d%d", &n, &m);
while (m--) {
scanf("%d%d", &a, &b);
edge[a].push_back(b);
}
for (int i = 1; i <= n; ++i) {
if (!dfsn[i]) {
tarjan(i);
}
}
return 0;
}
洛谷P2863
#include<cstdio>
#include<vector>
#include<stack>
#include<algorithm>
using namespace std;
const int N = 1e4 + 5;
vector<int> edge[N];
int dfsn[N], tot;//dfs序
int low[N];
stack<int> s;
bool in_stack[N];//是否在栈里
int scc[N], sc;//节点i所在scc编号
int sz[N];//强连通分量i的大小
void tarjan(int u) {
low[u] = dfsn[u] = ++tot;
s.push(u);
in_stack[u] = true;
for (int i = 0; i < edge[u].size(); ++i) {
int v = edge[u][i];
if (!dfsn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (in_stack[v]) {
low[u] = min(low[u], dfsn[v]);
}
}
if (dfsn[u] == low[u]) {
++sc;
while (s.top() != u) {
scc[s.top()] = sc;
++sz[sc];
in_stack[s.top()] = false;
s.pop();
}
scc[u] = sc;
++sz[sc];
in_stack[u] = false;
s.pop();
}
}
int main() {
int n, m, a, b, ans = 0;
scanf("%d%d", &n, &m);
while (m--) {
scanf("%d%d", &a, &b);
edge[a].push_back(b);
}
for (int i = 1; i <= n; ++i) {
if (!dfsn[i]) {
tarjan(i);
}
}
for (int i = 1; i <= sc; ++i) {
if (sz[i] > 1)++ans;
}
printf("%d\n", ans);
return 0;
}
相关文章
- 06-图1 列出连通集
- YbtOJ 604「强连通分量」字符变换
- 无向图的连通分量
- WordPress 网站使用 “微信机器人高级版” 插件连通微信公众号
- 2022-12-26:有一个数组包含0、1、2三种值, 有m次修改机会,第一种将所有连通的1变为0,修改次数-1, 第二种将所有连通的2变为1或0,修改次数-2
- 测试Linux网络连接测试:确保联接安全可靠(linux网络连通)
- flannel 的连通与隔离 – 每天5分钟玩转 Docker 容器技术(61)
- macvlan网络隔离和连通–每天5分钟玩转Docker容器技术(57)
- Linux轻松打开ICMP,网络连通问题迎刃而解(linux打开icmp)