有向图的强连通分量(Tanjan)

来源:互联网 发布:网络互动直播新闻 编辑:程序博客网 时间:2024/06/03 14:45

给定一个有向图,定义:

  • 强连通分量:在一堆点中,任意两点都可以互相到达

求所有的强联通分量

思路:

  • 记录一个点的时间戳和他能到达的最早点
  • 每深搜到一个点进队列,直到发现一个点能到达的最早点就是他自己,则把队尾一直到他的所有点输出,这就是一个强联通分量里的所有点
//Tanjan求强连通分量 #include<stack>#include<cstdio>#include<cstdlib>#include<iostream>#include<algorithm>using namespace std;const int MAXN = 1000 + 10;int n, m;int lowlink[MAXN], qiang[MAXN], qiang_cnt;int pre[MAXN], tim;stack<int> s;int head[MAXN], cnt;struct edge{    int to, next, num;} e[MAXN];void add(int u, int v, int y){    e[++cnt].next = head[u];    head[u] = cnt;    e[cnt].to = v;    e[cnt].num = y;}void dfs(int u){    pre[u] = lowlink[u] = ++tim;    s.push(u);    for(int i = head[u]; i; i = e[i].next)    {        int v = e[i].to;        if(!pre[v])        {            dfs(v);            lowlink[u] = min(lowlink[u], lowlink[v]);   //用后代所能到达的最早点更新u所能到达的最早点        }        else if(!qiang[v]) lowlink[u] = min(lowlink[u], pre[v]);   //如果遇到一个点已经讨论过,但是还没有加入任何强连通分量,则将他的时间戳与lowlink更新    }    if(lowlink[u] == pre[u])    {        qiang_cnt++;        while(1)        {            int x = s.top(); s.pop();            qiang[x] = qiang_cnt;            if(x == u) break;        }    }}int main(){    int n, m;    cin >> n >> m;    for(int i = 1; i <= m; i++)    {        int u, v; cin >> u >> v;        add(u, v, i);    }    for(int i = 1; i <= n; i++)        if(!pre[i]) dfs(i);    for(int k = 1; k <= qiang_cnt; k++)    {        for(int i = 1; i <= n; i++)            if(qiang[i] == k) cout << i << " ";        cout << endl;    }    return 0;}
0 0
原创粉丝点击