B3609 [图论与代数结构 701] 强连通分量(强连通分量)

B3609 [图论与代数结构 701] 强连通分量

题目描述

给定一张 n 个点 m 条边的有向图,求出其所有的强连通分量。

注意,本题可能存在重边和自环。

输入格式

第一行两个正整数 nm ,表示图的点数和边数。

接下来 m 行,每行两个正整数 uv 表示一条边。

输出格式

第一行一个整数表示这张图的强连通分量数目。

接下来每行输出一个强连通分量。第一行输出 1 号点所在强连通分量,第二行输出 2 号点所在强连通分量,若已被输出,则改为输出 3 号点所在强连通分量,以此类推。每个强连通分量按节点编号大小输出。

输入输出样例 #1

输入 #1

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

输出 #1

3
1 2 5 6
3
4

说明/提示

对于所有数据,1n100001m100000
这道题是一道标准的强连通分量的题,但我还是卡了好久,首先对于自环我们只需要判断a1=b就行了,对于重边,我用的是set容器,然后在出栈的时候我们需要存储每个点在第几个强连通分量当中,然后在遍历的过程中,如果改点所对应的强连通分量已经输出了,说明该点就已经输出了,此时我们直接跳过就行

#include<iostream>
#include<vector>
#include<stack>
#include<set>
#include<algorithm>
using namespace std;
const int N=1e5+5;
int n,m,a,b;
int low[N],dfsn[N],vis[N];
set<int>v[N];
vector<int>ans[N];
int vis1[N];
int vis2[N];
stack<int>s;
int t=0,cnt=0;
void dfs(int x){
    low[x]=dfsn[x]=++t;
    vis[x]=1;
    s.push(x);
for(auto i=v[x].begin();i!=v[x].end();i++){
    int y=*i;
    if(!dfsn[y]){
dfs(y);
low[x]=min(low[x],low[y]);
}
else if(vis[y])low[x]=min(low[x],dfsn[y]);
}
if(low[x]==dfsn[x]){
++cnt;
    while(s.top()!=x){
        ans[cnt].push_back(s.top());
        vis1[s.top()]=cnt;
        vis[s.top()]=0;
        s.pop();
    }
     ans[cnt].push_back(s.top());
        vis1[s.top()]=cnt;
        vis[s.top()]=0;
        s.pop();
}
}
int main(){
    cin>>n>>m;
    while(m--){
        cin>>a>>b;
        if(a!=b)v[a].insert(b);
}
for(int i=1;i<=n;i++)if(!dfsn[i])dfs(i);
cout<<cnt;
    cout<<endl;
    for(int i=1;i<=n;i++){
        int w=vis1[i];
        if(vis2[w])continue;
        vis2[w]=1;
        sort(ans[w].begin(),ans[w].end());
        for(int j=0;j<ans[w].size();j++)cout<<ans[w][j]<<" ";
        cout<<endl;
    }
    return 0;
}
posted @ 2025-03-15 14:34  郭轩均  阅读(27)  评论(0)    收藏  举报
相关博文:
阅读排行:
· 突发,CSDN 崩了!程序员们开始慌了?
· 完成微博外链备案,微博中直接可以打开园子的链接
· C# WinForms 实现打印监听组件
· C#实现欧姆龙 HostLink 通讯协议库
· 一个基于 .NET 开源、模块化 AI 图像生成 Web 用户界面
点击右上角即可分享
微信分享提示