有向图的强连通分量
概念
强连通图,如果vi到vj有路径,那么vj到vi也有路径那么就是一张强连通图
- 强连通图分量:如果图不是强连通图那么把连通部分和不连通部分分开 ,那么分开后的图就是强连通分量(俗话来解释)
样例
如图所示,得连通分量{1,2,3} {4} {5}
分析思路:
- 1,2,3相互连通且 根据tarjan算法 low 值都与最小节点1相等
- 4 到达 5,4的 low 值 等于四
- 5节点 的low和dfn 等于5 ,全图中只有一个节点的low等于5,返回四节点 确定是分量
- 到达四节点,全图只有一个节点的low等于四,返回一节点,确定是分量
代码实现
- 栈存储输出
- tarjan标记
#include <iostream>
#include <cstring>
#include <stack>
using namespace std;
const int N = 1e3;
int head[N];
typedef struct{
int to;
int next;
}node;
node edge[N*N];
int dfn[N],low[N],cnt,num;
int n,m;
bool visited[N];
stack <int> star;
void init(){
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(visited,false,sizeof(visited));
cnt = num = 0;
}
void tarjan(int u ){
dfn[u] = low[u] = ++cnt;
visited[u] = true;
star.push(u);
for (int i = head[u]; i != -1;i = edge[i].next){
int v = edge[i].to;
if(!dfn[v]){
tarjan(v);
low[u] = min(low[u],low[v]);
}else if(visited[v]){
low[u] = min(low[u],dfn[v]);
}
}
if(low[u] == dfn[u]){ // 强连通分量 有向图
int v;
cout << "强连通分量:";
do{
v = star.top();
star.pop();
cout << v << " ";
visited[v] = false;
}while(v!=u);
cout << endl;
}
}
int main(){
init();
cin >> n >> m;
int u,v;
for (int i = 0; i < m; i++)
{
cin >> u >> v;
edge[num].next = head[u];
edge[num].to = v;
head[u] = num++;
}
for(int i = 1; i <= n;i++){
if(!dfn[i])tarjan(i);
}
}