tarjan强连通分量缩点模板

Posted hesorchen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了tarjan强连通分量缩点模板相关的知识,希望对你有一定的参考价值。

强连通定义

百度百科 强连通图(Strongly Connected Graph):是指在有向图G中,如果对于每一对vi、vj,vi≠vj,从vi到vj和从vj到vi都存在路径,则称G是强连通图。有向图中的极大强连通子图称做有向图的强连通分量。

缩点

在算法竞赛中,将强连通分量(例如环)处理成点会减少很多工作量。

在这里插入图片描述

上图中,1、3、5、2、6是一个强连通分量,经过缩点之后,变成下图。

在这里插入图片描述

tarjan算法

强连通图有如下性质,从图中一点出发,能经过所有点返回到起点。

可以利用以上性质,结合深度优先搜索,如果某一时刻搜索到了一个被标记过的点,那么这一个回路上的点都属于同一个强连通分量。

代码实现

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

const int N = 105;
int n, m;
vector<int> edge[N];
vector<int> belong[N]; //同一个强连通分量中的点
int dfn[N];            //dfs序
int root[N];           //强连通分量的根结点
int cnt;               //强连通分量数量
int ct;
stack<int> st;
bool instack[N];
void tarjan(int pos)
{
    dfn[pos] = ++cnt;
    root[pos] = cnt;
    st.emplace(pos);
    instack[pos] = 1;
    for (auto v : edge[pos])
    {
        if (!dfn[v])
        {
            tarjan(v);
            root[pos] = min(root[pos], root[v]);
        }
        else if (instack[v])
            /*
        到达一个标记过而且还在栈中的点,
        那么这一个回路都同属于一个强连通分量
        */
            root[pos] = min(root[pos], dfn[v]);
    }

    if (root[pos] == dfn[pos])
    {
        ++ct;
        int node;
        do
        {
            node = st.top();
            st.pop();
            instack[node] = 0;
            belong[ct].emplace_back(node);
        } while (root[node] != dfn[node]);
    }
}
int main()
{
    cin >> n >> m;
    for (int i = 1; i <= m; ++i)
    {
        int u, v;
        cin >> u >> v;
        edge[u].push_back(v);
    }

    for (int i = 1; i <= n; i++)
        if (!dfn[i]) //图不一定连通
            tarjan(i);
    for (int i = 1; i <= n; i++)
        cout << i << ' ' << dfn[i] << endl;
    cout << ct << endl;
    for (int i = 1; i <= ct; i++)
        for (auto it : belong[i])
            cout << it << " belong to " << i << endl;
    return 0;
}
/*
7 9
1 3
5 1
1 6
2 5
6 2
3 4
3 5
5 6
2 7
*/

参考资料

  1. 图论——强连通分量(Tarjan算法)

  2. tarjan算法详解–关于图的连通性 & 连通分量

  3. 算法学习笔记(69): 强连通分量

以上是关于tarjan强连通分量缩点模板的主要内容,如果未能解决你的问题,请参考以下文章

P3387 模板缩点(Tarjan求强连通分量)

图论算法-Tarjan模板 缩点;割顶;双连通分量

缩点(tarjan求强连通分量)

tarjan——强连通分量+缩点

[强连通分量+Tarjan缩点]

POJ 1236(强连通分量/Tarjan缩点)