请不要在意不忍直视的函数名
分析来自: https://www.luogu.com.cn/blog/zyb2624936151/tarjan
注:明星==最受欢迎的牛
首先,不难发现,如果这所有的牛都存在同一个强联通分量里。那么它们一定互相受欢迎。
那么,我们怎么来找明星呢。
很简单,找出度为00的强联通分量中的点。这样可以保证所有的人都喜欢它,但是它不喜欢任何人,所以说不存在还有人事明星。
此题还有一个特殊情况:
如果有两个点分别满足出度为零的条件,则没有明星,这样无法满足所有的牛喜欢他。
有了上边的解释,题目就不是那么难了,代码如下
#include<bits/stdc++.h>
using namespace std;
int n,m,a,b;
struct oppo {
int to,next;
} rood[50004];
bool f[10004];
int head[10004],tot,t[10004],ans;
int dfn[10004],low[10004],time_,vis[10004],all,belong[10004];
void add(int from,int to) {
rood[++tot].to=to;
rood[tot].next=head[from];
head[from]=tot;
}
stack< int > v;
void Tarjan(int x) {
dfn[x]=low[x]=++time_;
v.push(x);
vis[x]=1;
for(int i=head[x]; i; i=rood[i].next) {
if(!dfn[rood[i].to])
Tarjan(rood[i].to);
low[x]=min(low[x],low[rood[i].to]);
}
if(dfn[x]==low[x]) {
belong[x]=++all;
int y;
do {
y=v.top();
v.pop();
belong[y]=all;
t[all]++;
} while(y!=x);
}
}
int main() {
cin>>n>>m;
for(int i=1; i<=m; i++) {
scanf("%d %d",&a,&b);
add(a,b);
}
for(int i=1; i<=n; i++)
if(!dfn[i]) Tarjan(i);
for(int i=1; i<=n; i++)
for(int j=head[i]; j; j=rood[j].next)
if(belong[i]!=belong[rood[j].to])
f[belong[i]]=1;
for(int i=1; i<=all; i++)
if(!f[i])
if(ans) {
puts("0");
return 0;
} else
ans=t[i];
cout<<ans<<endl;
return 0;
}
有个地方想不通,最后求出度为零的强连通分量内部点个数,y总说强连通分量内部的点都是可以互相到达的那么应该从终点(唯一一个出度为零的点)出发也可以达到强连通分量内部的其他点但是这和终点本身的定义就相互违背了不是吗