版权声明:反正没人看 随意转载 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;
}