经典的tarjan缩点题qwq
先把爱慕关系构一个有向图,因为爱慕关系可继承,所以在同一个强连通分量中的所有牛都互相爱慕
因此我们可以利用tarjan进行缩点,将那些互相爱慕的牛们看做一头牛。
缩点后的奶牛们就不会有互相爱慕的关系了,因此我们可以分析出只有不爱慕他人的牛才可能当明星(噗
于是我们就找缩点后出度为0的点。
但如果有多个点出度为0,那么它们都当不了明星(它们没有受到对方的爱慕—>它们没有受到所有牛的爱慕)。
得出结论:
1.缩点后,若只有一个出度为0的点,那么明星牛的个数即那个强连通分量包含的点的个数;
2.缩点后,若有多个出度为0的点或无出度为0的点,那么明星牛的个数即为0。
代码奉上qwq
//Author:502BadGTway
#include<bits/stdc++.h>
using namespace std;
int n,m,fst[10010],v[100010],nex[100010],a,b,dfn[10010],low[10010];
int scc[10010],t,cnt,size[10010],minn[10010],out[10010],cont,ans;
bool f[10010];
stack<int> s;
void tarjan(int k)
{
low[k]=dfn[k]=++t;
f[k]=true;
s.push(k);
for(int i=fst[k];i!=-1;i=nex[i])
{
if(!dfn[v[i]])
{
tarjan(v[i]);
low[k]=min(low[k],low[v[i]]);
}
else
{
if(f[v[i]])
low[k]=min(low[k],dfn[v[i]]);
}
}
if(low[k]==dfn[k])
{
f[k]=false;
scc[k]=++cnt;
size[cnt]=1;
while(s.top()!=k)
{
scc[s.top()]=cnt;
f[s.top()]=false;
size[cnt]++;
s.pop();
}
s.pop();
}
return ;
}
int main()
{
cin>>n>>m;
memset(fst,-1,sizeof(fst));
memset(low,0x7f/3,sizeof(low));
for(int i=1;i<=m;i++)
{
scanf("%d%d",&a,&b);
nex[i]=fst[a];
v[i]=b;
fst[a]=i;
}
for(int i=1;i<=n;i++)
{
if(!dfn[i])
{
t=0;
tarjan(i);
}
}
for(int i=1;i<=n;i++)
{
for(int j=fst[i];j!=-1;j=nex[j])
{
if(scc[i]!=scc[v[j]])
out[scc[i]]++;
}
}
for(int i=1;i<=cnt;i++)
{
if(out[i]==0)
{
cont++;
ans+=size[i];
}
}
if(cont==1)
{
cout<<ans;
}
else
cout<<0;
return 0;
}