首页 > 其他分享 >tarjan

tarjan

时间:2022-10-05 17:46:34浏览次数:35  
标签:tarjan int 连通 dfn low 分量

终于来到了差点让我破防的tarjan

争取说明白吧

定义:

1. 桥:指去掉该边,其原本所在的强连通分量变为两部分(即不再是强连通分量)

2. 边双连通分量:即没有无向连通图

3. 强连通分量:即没有桥的有向连通图

 

求无向图的边双连通分量的数量


我们的思路是,从某一节点作为根节点开始dfs遍历图,使用一个$dfn$记录该节点的$dfs$序

再用一个$low$,记录这个点可以往上跑,跑到的最高的点的$dfn$的值

显然,如果$dfn[i] > low[i]$,则说明该节点可以查到自己的祖先,记作种类2

那如果$dfn[i] = low[i]$ ,就说明这个点就是所在连通分量的最上面一个点,记作种类1

我们开一个栈,然后访问到一个点就把这个点压入栈中

对于种类2,必然在栈中位于种类1的前面(因为后遍历到)

所以一旦发现点p为种类1,直接弹栈至p,其中弹出的所有元素都跟p在一个强连通分量里

代码如下:

#include<iostream>
#include<cstdio>
#include<stack>
#define NUM 1010
#define FOR(a,b,c) for( int a = b;a <= c;a++ )
using namespace std;

int n;
int a[NUM];
struct bian{
    int next,to;
};
bian e[NUM];
int head[NUM];
int dfn[NUM],low[NUM];
int id[NUM];
int cnt,scc;

void add( int x,int y ){
    e[++cnt].next = head[x];
    e[cnt].to = y;
    head[x] = cnt;
}
int timess;
stack <int> st;
bool ins[NUM];//判断这个点是不是已经在栈里了
void tarjan( int p ){
    dfn[p] = ++timess;
    low[p] = timess;//更新时间戳
    st.push( p );ins[p] = 1;//将该点压入栈中
    for( int i = head[p];i;i = e[i].next ){
        int to = e[i].to;
        if( !dfn[to] ){ //如果终点没有访问过
            tarjan( to );
            low[p] = min( low[p],low[to] );
        }else if( ins[to] ) //已经在栈里说明之前已经访问过,是之前的点
            low[p] = min( dfn[to],low[p] ); 
    }
    if( dfn[p] == low[p] ){ //以下是一个独立的强连通分量
        ++scc;//分量数++
        int hao;//栈顶点编号
        do{
            hao = st.top();
            st.pop();
            id[hao] = scc;//该点所在的分量编号
        }while( hao != p );//从栈顶到该点是一个连通分量
    }  
}
int m;
int main(){
    
    cin >> n >> m;
    FOR( i,1,m ){ //边数
        int x,y;
        cin >> x >> y;
        add( x,y );//有向边
    }
    
    FOR( i,1,n )
        if( !dfn[i] )
            tarjan( i );

    cout << "\n\n";

    FOR( i,1,n ) //输出每个点所在的连通块编号
        cout << i << " " << id[i] << "\n";
    
    return 0;
}
tarjan求强连通分量

 

边双连通分量

 

 


 

标签:tarjan,int,连通,dfn,low,分量
From: https://www.cnblogs.com/xiao-en/p/16471933.html

相关文章

  • Luogu P3469 [POI2008]BLO-Blockade(tarjan求割点)
    题目链接:https://www.luogu.com.cn/problem/P3469 [POI2008]BLO-Blockade题面翻译B城有$n$个城镇,$m$条双向道路。每条道路连结两个不同的城镇,没有重复的道路,所有......
  • Tarjan
    P3387【模板】缩点(强连通分量+拓扑+dp)#include<iostream>#include<queue>#include<cmath>#definefor1(i,a,b)for(inti=a;i<=b;i++)#definemp(a,b)make_pai......
  • Tarjan问题
    强连通学习资料强连通,又名\(scc\),即有向图中可以相互到达的子图,如\(\quad\)3->4;4->33与4即一对\(scc\);\(Tarjan\)的作用可以将有环图转为有向无环图既然是有向无......
  • 洛谷P1262 间谍网络(tarjan求强连通分量+缩点)
    题目链接:https://www.luogu.com.cn/problem/P1262思路:首先,我们能够知道,入读为0的点如果不能被收买的话,那么此题是无解的。其次,如果图中存在环的话,那么环中每个点的......
  • 洛谷P2002 消息扩散(tarjan缩点)
    题目链接:https://www.luogu.com.cn/problem/P2002思路:由于图中每个强连通分量(scc)中的点是可以互相到达的,所以我们可以用tarjan求图中scc,然后将所有scc缩点,最后求缩点之......
  • tarjan算法求强连通分量
    \(tarjan\)算法求强连通分量\(tarjan\)算法简介我在这篇博客中讲过\(tarjan\)算法的简介和求割点与桥,就不再讲述。强连通分量强连通图是指一个有向图内任意两点都能互......
  • tarjan
    changelog:新建此随笔,还有一些东西未完工。https://www.youtube.com/watch?v=TyWtx7q2D7Y有向图的DFS生成树主要有4种边(不一定全部出现):树边(treeedge):示意图中以黑色......