【题目链接】 https://vjudge.net/contest/280753#problem/C
题意: 给一个有向图,问其中有多少个点满足整个图除自身之外所有点能够到达它
思路: 用tarjan算法求解强联通分量,把每个强连通分量缩成一个点,统计出度为0的点,若出度为0的点不止一个,则不存在,反之只有一个,则统计那个强连通分量中有多少个点
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
const int N=10000;
struct node
{
int to,next;
}edge[50005];
int n,m;
int head[N+5];
int dfn[N+5];
int low[N+5];
int _stack[N+5];
int num[N+5];
int degree[N+5];
bool vis[N+5];
int cou,time,ans,top;
void init()
{
cou=0;time=1;ans=0;top=0;
memset(head,-1,sizeof head);
memset(num,0,sizeof num);
memset(degree,0,sizeof degree);
memset(low,0,sizeof low);
memset(vis,0,sizeof vis);
memset(dfn,0,sizeof dfn);
}
void add_edge(int u,int v)
{
edge[cou].to=v;
edge[cou].next=head[u];
head[u]=cou++;
}
void targan(int u)
{
low[u]=dfn[u]=time;
time++;
vis[u]=true;
_stack[top++]=u;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(!vis[v])
{
targan(v);
low[u]=min(low[u],low[v]);
}
else
low[u]=min(low[u],dfn[v]);
}
if(low[u]==dfn[u])
{
ans++;
while(top&&_stack[top]!=u)
{
top--;
vis[_stack[top]]=true;
num[_stack[top]]=ans;
}
}
}
int main()
{
cin>>n>>m;
init();
int u,v;
for(int i=0;i<m;i++)
{
cin>>u>>v;
add_edge(u,v);
}
for(int i=1;i<=n;i++)
{
if(!vis[i])
targan(i);
}
for(int i=1;i<=n;i++)
{
for(int j=head[i];j!=-1;j=edge[j].next)
{
if(num[i]!=num[edge[j].to])
{
degree[num[i]]++;
}
}
}
int sum=0,x,res;
for(int i=1;i<=ans;i++)
{
if(!degree[i])
{
sum++;
x=i;
}
}
if(sum==1)
{
res=0;
for(int i=1;i<=n;i++)
{
if(num[i]==x)
{
res++;
}
}
cout<<res<<endl;
}
else
cout<<"0"<<endl;
return 0;
}