有向图的强连通分量 SCC tarjin算法

来源:互联网 发布:mycard点卡淘宝 编辑:程序博客网 时间:2024/05/22 06:25


这个本来是暑假的时候学图连通性的时候一起学的。没整理出来,又有些遗忘。

现在在 2-sat 里用到它来缩点。先写个简略版的。

算法:

dfn[]、low[]初始为++num(排除0),

tarjin到u入栈s,ins[u] = 1;

遍历u的所有邻点v(邻接表),

对没有tarjin的点(dfn[v]=0),tarjin(v),low[u] = min(low[u], low[v])。

对tarjin过,并还在栈中的点,low[u] = min(low[u], dfn[v])。

遍历完后,

如果dfn[u] == low[u],

栈顶v出栈,直到u==v。同一时间出栈的即为一个强连通分量。


代码:

//求 有向图 强连通分支tarjin算法//类似求无向图割点、桥、双连通分支#include<cstdio>#include<cstring>#include<iostream>#include<stack>using namespace std;#define FF(x1, x2) for(int i=x1;i<x2; i++)#define TOMIN(x1, x2) x1=x1<x2?x1:x2;#define MAXN 100#define MAXM 100struct edge{int u, v;} a[MAXM];int first[MAXN], next[MAXM];int n, m;void addedge(int u, int v, int e) {next[e]=first[u]; first[u]=e; a[e].u=u; a[e].v=v;}void read_graph() {cin>>n>>m; FF(0, m){int u,v; cin>>u>>v; addedge(u, v, i);} }int dfn[MAXN], low[MAXN];int num;stack<int> s;int ins[MAXN];void tarjin(int u){dfn[u] = low[u] = ++num;s.push(u);ins[u] = 1;for(int e=first[u]; e!=-1; e=next[e]){int v=a[e].v;if(!dfn[v]){tarjin(v);TOMIN(low[u], low[v]);}else if(ins[v]){TOMIN(low[u], dfn[v]);}}if(dfn[u]==low[u]){while(1){int v=s.top();s.pop();ins[v] = 0;cout<<v<<" ";if(u == v) break;}cout<<endl;}}int  main(){num=0;//点赋值memset(dfn, 0, sizeof(dfn));memset(first, -1, sizeof(first));memset(ins, 0, sizeof(ins));read_graph();FF(1, n+1){if(!dfn[i])tarjin(i);}}/*input6 81 33 55 61 24 12 44 63 4output6 5 3 4 2 1 */


原创粉丝点击