首页 > 其他分享 >Tarjan求边双联通分量

Tarjan求边双联通分量

时间:2024-10-25 15:11:51浏览次数:7  
标签:nxt Tarjan 联通 int dfn low now 求边 eid

更新日志

思路

首先,我们求出原图中所有的桥,然后跑DFS给原图分区。

求桥具体过程:Tarjan求桥

更具体的,我们遍历每一个点,假如这个点没有被分区,那么就从这个点开始深搜。

每一次深搜,都走不是桥的边,那么走到的就都属于一个边双。(很容易证明)

这样,我们把每一次深搜走到的所有点分成一个边双,储存相应信息即可。

细节

提醒一个小点吧,如果你和我一样使用原边编号储存所有桥(详见求桥部分),那么在判断的时候也应该使用原无向边编号。

模板

注:dfs函数的使用详见例题代码

int dcnt;
int dfn[N],low[N];
bool bri[M];
void tarjan(int now,int fed){
    dfn[now]=low[now]=++cnt;
    for(int e=hd[now];e;e=ne[e]){
        int nxt=to[e],eid=(e-1)/2+1;
        if(!dfn[nxt]){
            tarjan(nxt,eid);
            low[now]=min(low[now],low[nxt]);
            if(low[nxt]>dfn[now]){
                bri[eid]=true;
            }
        }else if(eid!=fed)low[now]=min(low[now],dfn[nxt]);
    }
}
int bcnt;
int bcc[N];
veci nods[N];
void dfs(int now){
    bcc[now]=bcnt;
    nods[bcnt].push_back(now);
    for(int e=hd[now];e;e=ne[e]){
        int nxt=to[e],eid=(e-1)/2+1;
        if(bcc[nxt]!=0||bri[eid])continue;
        dfs(nxt);
    }
}

例题

LG8436

代码

前注:非题解,不做详细讲解

#include<bits/stdc++.h>
using namespace std;

typedef vector<int> veci;

const int N=5e5+5,M=2e6+5;

int n,m;

int cnt;
int hd[N],to[M*2],ne[M*2];
void adde(int u,int v){
    to[++cnt]=v;
    ne[cnt]=hd[u];
    hd[u]=cnt;
}

int dcnt;
int dfn[N],low[N];
bool bri[M];
void tarjan(int now,int fed){
    dfn[now]=low[now]=++cnt;
    for(int e=hd[now];e;e=ne[e]){
        int nxt=to[e],eid=(e-1)/2+1;
        if(!dfn[nxt]){
            tarjan(nxt,eid);
            low[now]=min(low[now],low[nxt]);
            if(low[nxt]>dfn[now]){
                bri[eid]=true;
            }
        }else if(eid!=fed)low[now]=min(low[now],dfn[nxt]);
    }
}
int bcnt;
int bcc[N];
veci nods[N];
void dfs(int now){
    bcc[now]=bcnt;
    nods[bcnt].push_back(now);
    for(int e=hd[now];e;e=ne[e]){
        int nxt=to[e],eid=(e-1)/2+1;
        if(bcc[nxt]!=0||bri[eid])continue;
        dfs(nxt);
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>m;
    int a,b;
    for(int i=1;i<=m;i++){
        cin>>a>>b;
        adde(a,b);
        adde(b,a);
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i])tarjan(i,0);
    }
    for(int i=1;i<=n;i++){
        if(!bcc[i]){
            ++bcnt;
            dfs(i);
        }
    }
    cout<<bcnt<<"\n";
    for(int i=1;i<=bcnt;i++){
        cout<<nods[i].size()<<" ";
        for(auto j:nods[i])cout<<j<<" ";
        cout<<"\n";
    }
    return 0;
}

标签:nxt,Tarjan,联通,int,dfn,low,now,求边,eid
From: https://www.cnblogs.com/HarlemBlog/p/18502587

相关文章

  • Tarjan求割边(桥)
    更新日志思路割边定义与割点相似,不过是把点换成了边,所以思想和割点差不多。Tarjan割点我们只需要在Tarjan过程中判断某一颗子树的low是否严格大于当前节点的dfn。值得注意,这里子树的low不应该由到它的原边回溯到它的父节点得到!究其原因,其实就是如果子树是一个强连通分量,那......
  • Ubuntu20.04LTS aarch64 操作系统连接联通4G网卡
    步骤1:更新系统并安装必要的软件包sudoapt-getupdatesudoapt-getinstallusb-modeswitchmodemmanagernetwork-managerusb-modeswitch:用于将某些USB设备从存储模式切换到调制解调器模式。ModemManager:用于管理移动宽带调制解调器。NetworkManager:用于管理网络连接。......
  • 浅谈 tarjan
    就是记录两个数组:dfn[]和low[]其中dfn[]表示访问的顺序,low[u]用来存储\(u\)不经过其父亲能到达的最小时间戳。。。搬一下wiki的图。。。我们发现\(low[v]\gedfn[u]\)可以表示不能回到祖先,则\(u\)点位割点。。。直接上代码P3388------>#include<bits/stdc++.h>usi......
  • Tarjan求强连通分量
    思路首先建成DFS树,对于每个节点,储存两个信息:dfn与low。每当遍历到一个节点,就将其压入栈中,作用后面会说。dfn储存一个节点的dfs序,low储存一个节点的子树能够到达的在栈中的最小dfs序。首先有一个性质,每个节点子树中所有节点的dfn必然大于当前节点的。那么,假如一个节点的low小......
  • Tarjan缩点题单 刷题题解
    Tarjan缩点可以将一个图的每个强连通分量缩成一个点,然后构建新图,该图就会变成一个有向无环图。变成有向无环图之后就能结合最短路,拓扑......解决相应题目洛谷题单分享:https://www.luogu.com.cn/training/526565前几道是绿题,没什么好写的,大致过一下1.强连通分量题目链接:https:......
  • 联通云数据中心
    中国联通(香港)将军澳智·云数据中心:打造境外通信服务新标杆在数字化浪潮席卷全球的今天,数据中心作为信息社会的基石,其重要性日益凸显。中国联通(香港)将军澳智·云数据中心,作为中国联通全资拥有并运营的境外综合性通信枢纽大楼,不仅是中国联通在境外最大的综合电信服务枢纽,更是中......
  • 为什么选择我们联通的的SD-WAN?
    随着企业业务的全球化发展,对于高效、灵活且成本可控的网络连接解决方案的需求日益增长。SD-WAN(软件定义广域网)作为一种创新技术应运而生,它利用互联网而非传统的专线接入方式来实现终端路由器的自动配置和快速连网。中国联通国际公司提供的SD-WAN服务不仅能够帮助企业构建起一个适......
  • $Tarjan$强连通分量
    有向图缩点非常板,先缩点再拓扑。其实\(Tarjan\)强连通分量缩点往往与拓扑排序求最长路(或其他)密切相关。有向图缩点问有向图上哪个点,其它点都能走到它题面,先缩点,看缩完后有哪些点出度为\(0\),若有多个,则无解,否则即为那一个。最大半联通子图题面先缩点,可以发现缩点后最大半联通......
  • 联通分量
    点双:在一个联通块中删去任意一个点后剩下的点仍然能构成联通块,则此联通块叫做点双联通分量。(两个点是一个点双)性质:任意两点间可构造出两条不相交路径(除起点和终点外不重复经过其他点)。割点:在一联通块中删去一点可使剩下的点不联通,则此点叫做割点。一个点可能在多个点双里。边......
  • Tarjan
    强连通分量前置知识强连通:一张有向图的节点两两互相可达。连通分量:若\(H\)是\(G\)的一个连通子图,且不存在\(F\)使得\(H\subsetneqF\subseteqG\),则\(H\)为\(G\)的一个连通分量(也叫连通块)Tarjan求强连通分量DFS生成树(用的OI-wiki的图)树边:图中的黑边,每次搜索找到一......