tarjan求强连通分量入门

#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<stack>

using namespace std;
const int maxn = 1e5 + 10;

struct node
{
    int next, to;
};
int tot, cnt, deep;
node edge[maxn<<1];
int dfn[maxn], color[maxn], low[maxn], vis[maxn], num[maxn];
int head[maxn];
stack<int>Q;

void add(int u, int to)
{
    edge[tot] = (node){head[u], to};
    head[u] = tot++;
}
void tarjan(int u)
{
    vis[u] = 1;
    dfn[u] = ++deep;
    low[u] = deep;
    Q.push(u);
    for(int i = head[u]; ~i; i = edge[i].next)
    {
        int v = edge[i].to;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else
        {
            if(vis[v])
            {
                low[u] = min(low[u], low[v]); // dfn[v];
            }
        }
    }
    if(dfn[u] == low[u])
    {
        color[u] = ++cnt;
        vis[u] = 0; // 别漏了,会造成u在栈里面的假象
        while(Q.top() != u)
        {
            color[Q.top()] = cnt;
            vis[Q.top()] = 0;
            Q.pop();
        }
        Q.pop();
    }
}

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    cnt = 0;
    deep = 0;
    memset(head, -1, sizeof(head));
    tot = 0;
    for(int i = 0; i < m; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        add(u, v);
    }
    for(int i = 1; i <= n; i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    for(int i = 1; i <= n; i++)
    {
        num[color[i]]++;
    }
    int ans = 0;
    for(int i = 1; i <= cnt; i++)
    {
       // printf("%d\n", num[i]);
        if(num[i] > 1)
            ans++;
    }
    printf("%d\n", ans);
    return 0;

}

发布了40 篇原创文章 · 获赞 13 · 访问量 849

猜你喜欢

转载自blog.csdn.net/weixin_43891021/article/details/102759907
今日推荐