P8436 【模板】边双连通分量

P8436 【模板】边双连通分量

题目描述

对于一个 n 个节点 m 条无向边的图,请输出其边双连通分量的个数,并且输出每个边双连通分量。

输入格式

第一行,两个整数 nm

接下来 m 行,每行两个整数 u,v,表示一条无向边。

不保证图为简单图,图中可能有重边和自环。

输出格式

第一行一个整数 x 表示边双连通分量的个数。

接下来的 x 行,每行第一个数 a 表示该分量结点个数,然后 a 个数,描述一个边双连通分量。

你可以以任意顺序输出边双连通分量与边双连通分量内的结点。

输入输出样例 #1

输入 #1

5 8
1 3
2 4
4 3
1 2
4 5
5 1
2 4
1 1

输出 #1

1
5 1 5 4 2 3

输入输出样例 #2

输入 #2

5 3
1 2
2 3
1 3

输出 #2

3
3 1 3 2
1 4
1 5

输入输出样例 #3

输入 #3

6 5
1 3
2 4
1 2
4 6
2 3

输出 #3

4
3 1 2 3
1 4
1 5
1 6

输入输出样例 #4

输入 #4

7 8
1 3
2 4
3 5
2 5
6 4
2 5
6 3
2 7

输出 #4

3
1 1
5 2 5 3 6 4
1 7

说明/提示

样例四解释:

相同颜色的点为同一个连通分量。


数据范围:
对于 100% 的数据,1n5×1051m2×106

subtask n m 分值
1 1n100 1m500 25
2 1n5000 1m5×104 25
3 1n2×105 1m5×105 25
4 1n5×105 1m2×106 25

数据更新

  • 2022/7/14 加强数据
  • 2022/11/26 新增 10 组较小的数据(1n,m10),方便选手调试。
  • 2022/12/31 重组 subtask,并加入若干组极端数据。
  • 2023/1/1 发现昨天新加入的数据数据出了问题,已修改。

本题不卡常,时间限制与空间限制均已开大,正确的解法均可通过。


惊喜:AC 后记得把鼠标放到测试点上看反馈信息,有惊喜哦。

#include<iostream>
#include<vector>
#include<stack>
#define int long long 
using namespace std;
struct edge{
    int x,y;
};
const int N=5*1e5+5;
int n,m,t=0,cnt=0,low[N],dfsn[N],a,b;
vector<edge>v;
vector<int>h[N];
vector<int>dcc[N];
stack<int>s;
void dfs(int x,int fa){
    low[x]=dfsn[x]=++t;
    s.push(x);
    for(int i=0;i<h[x].size();i++){
        int j=h[x][i],y=v[j].y;
        if(!dfsn[y]){
            dfs(y,j);
            low[x]=min(low[x],low[y]);
            if(low[y]>dfsn[x]){
                ++cnt;
                while(1){
                    int z=s.top();
                    s.pop();
                    dcc[cnt].push_back(z);
                    if(z==y)break;
                }
            }
        }
        else if(j!=(fa^1))low[x]=min(low[x],dfsn[y]);
    }
}
signed main(){
    cin>>n>>m;
    for(int i=0;i<m;i++){
        cin>>a>>b;
        v.push_back({a,b});
        h[a].push_back(v.size()-1);
        v.push_back({b,a});
        h[b].push_back(v.size()-1);
    }
    for(int i=1;i<=n;i++){
        if(!dfsn[i]){
            dfs(i,0);
        }
        if(!s.empty()){
            ++cnt;
            while(!s.empty()){
                dcc[cnt].push_back(s.top());
                s.pop();
            }
        }
    }
    cout<<cnt<<endl;
    for(int i=1;i<=cnt;i++){
        cout<<dcc[i].size()<<" ";
        for(int j:dcc[i])cout<<j<<" ";
        cout<<endl;
    }
    return 0;
}
posted @ 2025-03-21 21:52  郭轩均  阅读(46)  评论(0)    收藏  举报
相关博文:
阅读排行:
· 提升Avalonia UI质感,跨平台图标库选型实践
· 突发,CSDN 崩了!程序员们开始慌了?
· C# 中委托和事件的深度剖析与应用场景
· 一个基于 .NET 8 + Ant Design Blazor 开发的简洁现代后台管理框架
· AppBox拖拽设计增删改查用户界面
点击右上角即可分享
微信分享提示