连通性问题(有向图)(未完结)
强连通分量
我们首先定义两种边:返祖边为从一个点指向其祖先的边;横叉边从某个点指向树中另一个子树中的点的边。两者统称为非树边。而剩下的边即为树边,树边也就是再搜索树上的边。
我们定义
于是我们便有了求出
void tar(int u){
low[u]=dfn[u]=++tot;
stk[++top]=u;
ist[u]=1;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tar(j);
low[u]=min(low[u],low[j]);
}
else if(ist[j]){
low[u]=min(low[u],dfn[j]);
}
}
}
接着我们考虑怎么通过
我们假设现在遇到了一个点
换句话说,
于是我们不断弹出栈,直到弹出了
完整代码:
#include<bits/stdc++.h>
#define int long long
#define N 10005
#define M 100005
using namespace std;
int n,m,h[N],e[M],ne[M],idx,cnt,tot;
int stk[N],col[N],dfn[N],low[N],top;
bool ist[N],st[N];
vector<int>res[N];
void add(int a,int b){
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void tar(int u){
low[u]=dfn[u]=++tot;
stk[++top]=u;
ist[u]=1;
for(int i=h[u];~i;i=ne[i]){
int j=e[i];
if(!dfn[j]){
tar(j);
low[u]=min(low[u],low[j]);
}
else if(ist[j]){
low[u]=min(low[u],dfn[j]);
}
}
if(dfn[u]==low[u]){
cnt++;
int y;
do{
y=stk[top--];
ist[y]=0;
col[y]=cnt;
res[cnt].push_back(y);
}while(y!=u);
}
}
signed main(){
cin>>n>>m;
memset(h,-1,sizeof h);
for(int i=1;i<=m;i++){
int a,b;
cin>>a>>b;
add(a,b);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
tar(i);
}
}
cout<<cnt<<'\n';
for(int i=1;i<=n;i++){
if(!st[col[i]]){
sort(res[col[i]].begin(),res[col[i]].end());
for(auto it:res[col[i]]){
cout<<it<<' ';
}
cout<<'\n';
st[col[i]]=1;
}
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】