P2002 消息扩散
先缩点,然后统计有几个入度为零的点。
然而有重边和自环。
自环需要判断一下,然而重边也许不需要判断?
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;
int from[500010],to[500010],nex[500010],head[100010];
int dfn[100010],low[100010],scc[100010],enter[100010];
int sccnum,dfsnum,instack[100010];
stack <int> s;
void tarjan(int u)
{
dfn[u]=low[u]=++dfsnum;
instack[u]=1;
s.push(u);
for(int i=head[u];i;i=nex[i])
{
if(!dfn[to[i]])
{
tarjan(to[i]);
low[u]=min(low[u],low[to[i]]);
}
else if(instack[to[i]])
low[u]=min(low[u],dfn[to[i]]);
}
if(dfn[u]==low[u])
{
int v;
++sccnum;
do
{
v=s.top();
s.pop();
instack[v]=0;
scc[v]=sccnum;
}while(u!=v);
}
return ;
}
int main()
{
ios::sync_with_stdio(false);
int n,m,x,y,ans=0;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
cin>>x>>y;
from[i]=x;
to[i]=y;
nex[i]=head[x];
head[x]=i;
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=m;i++)
if(scc[from[i]]!=scc[to[i]])
++enter[scc[to[i]]];
for(int i=1;i<=sccnum;i++)
if(enter[i]==0)
++ans;
cout<<ans;
return 0;
}