Tarjan算法
Tarjan算法中几个关键点:
当dfn[u]和low[u]相等时说明,找到一个强连通分量,这时需要进行弹栈操作,并将同一个连通分量中的所有点都缩成一个点,也就是常说的缩点操作
代码模板:
下面这个是将缩好的点看成一个新的图,然后判断如何连通
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e7+5;
int dfn[maxn],low[maxn],head[maxn],sstack[maxn],t[maxn],in[maxn];
int cnt,num,n,tot,tt,m;
bool instack[maxn];
struct edge{
int to,next;
}e[maxn];
void add_edge(int u,int v){
e[cnt].next = head[u];
e[cnt].to = v;
head[u] = cnt++;
}
void tar(int u){
dfn[u] = low[u] = ++tot;
instack[u] = true;
sstack[++num] = u;
for(int i = head[u] ; i != -1 ; i = e[i].next){
int v = e[i].to;
if(!dfn[v]){
tar(v);
low[u] = min(low[u],low[v]);
}
else if(instack[v]) low[u] = min(dfn[v],low[u]);
}
if(dfn[u] == low[u]){
while(u != sstack[num]){
instack[sstack[num]] = false;
t[sstack[num]] = tt;
num--;
}
instack[u] = false;
t[u] = tt;
tt++;
num--;
}
}
int main(){
cin >> n >> m;
memset(head,-1,sizeof(head));
memset(instack,false,sizeof(instack));
for(int i = 0 ; i < m ; i++){
int u,v;
cin >> u >> v;
if(u != v)
add_edge(u,v);
}
for(int i = 1 ; i <= n ; i++){
if(!dfn[i]) tar(i);
}
int ans = 0;
for(int i = 1 ; i <= n ; i++){
for(int j = head[i] ; j != -1 ; j = e[j].next){
int v = e[j].to;
if(t[i] != t[v]) in[t[v]] = 1;
}
}
for(int i = 0 ; i < tt ;i++){
if(!in[i]) ans++;
}
cout << ans << endl;
return 0;
}
I'm so cute. Please give me money.
- 本文链接:http://yoursite.com/2020/08/08/%E5%BC%BA%E8%BF%9E%E9%80%9A%E5%88%86%E9%87%8F/
- 版权声明:本博客所有文章除特别声明外,均默认采用 许可协议。

若没有本文 Issue,您可以使用 Comment 模版新建。
GitHub IssuesGitHub Discussions