计蒜客 受欢迎的蒜头君 【tarjan求缩点】

版权声明:反正没人看 随意转载 https://blog.csdn.net/qq_38930523/article/details/84070170

题目描述

在这里插入图片描述

思路

因为关系具有传递性,我们可以把强连通分量看做是一个点。然后利用tarjan算法,将图上所有的强连通分量缩成一个点,最后我们只处理这样新处理出来的图;因为这是一张DAG(有向无环图),要使所有的顶点有到某一点的通路,即可以求出所有出度为0的点。 由于是DAG,所以不可能存在出度为0的点的个数是0;
出度为0的顶点的个数只可能 >= 0, 当这样的点存在1个时,我们输出这个顶点所在的环的大小即可,当出度为0的顶点的个数 >= 2 时, 此时代表一开始的图就不是强连通图,此时输出0即可;

AC代码

#include <bits/stdc++.h>
using namespace std;

#define MAX_N 10010

stack<int> S;
vector<int> g[MAX_N], scc[MAX_N];
int in_stack[MAX_N], dfn[MAX_N], low[MAX_N], idx = 1, ans_scc = 0, belong[MAX_N], out[MAX_N];

void tarjan(int u)
{
    low[u] = dfn[u] = idx++;
    S.push(u);
    in_stack[u] = 1;
    for(int i = 0; i<g[u].size(); i++)
    {
        int v = g[u][i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u], low[v]);
        }
        else if(in_stack[v])
        {
            low[u] = min(low[u], dfn[v]);
        }
    }
    if(dfn[u] == low[u])
    {
        ans_scc++;
        do
        {
            int k = S.top();
            belong[k] = ans_scc;
            in_stack[k] = false;
            S.pop();
            scc[ans_scc].push_back(k);
            if(u == k)
                break;
        }
        while(!S.empty());
    }
}

int main()
{
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 0; i<m; i++)
    {
        int x, y;
        scanf("%d %d", &x, &y);
        g[x].push_back(y);
    }
    memset(dfn, 0, sizeof(dfn));
    for(int i = 1; i<=n; i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    for(int i = 1; i<=n; i++)
    {
        int sz = g[i].size();
        for(int j = 0; j < sz; j++)
        {
            int v = g[i][j];
            if(belong[v] != belong[i])
            {
                out[belong[i]]++;
            }
        }
    }
    int tmp = 0,  ans;
    for(int i = 1; i<=ans_scc; i++)
    {
        if(out[i] == 0)
        {
            tmp++;
            ans = scc[i].size();
        }
    }
    if(tmp != 1)
    {
        cout << 0;
    }
    else
        cout << ans;
    return 0;
}


猜你喜欢

转载自blog.csdn.net/qq_38930523/article/details/84070170
今日推荐