这道题明显是一个图论,告诉了你受欢迎的关系是具有传递性的就意味着可以用图来存。先将问题简单化,如果这种关系是一棵树,那么答案一定是树根。当然如果是森林,答案就是所有的树根。那么我们如何将图转换成树呢?用Tarjan缩点即可。用Tarjan缩点后答案即为所有连通块中入度为0的连通块的个数。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
#define maxn 50005
int pre[maxn],last[maxn],other[maxn],l;
int dfn[maxn],low[maxn],dfs_clock,scc_cnt,scc[maxn];
int n,m,in0[maxn],out0[maxn],siz[maxn],ans;
stack<int> s;
void connect(int x,int y)
{
l++;
pre[l]=last[x];
last[x]=l;
other[l]=y;
}
void dfs(int u)
{
dfn[u]=low[u]=++dfs_clock;
s.push(u);
for (int p=last[u];p;p=pre[p])
{
int v=other[p];
if (!dfn[v])
{
dfs(v);
low[u]=min(low[u],low[v]);
}
else if (!scc[v]) low[u]=min(low[u],dfn[v]);
}
if (dfn[u]==low[u])
{
scc_cnt++;
while (1)
{
int x=s.top();s.pop();
scc[x]=scc_cnt;
siz[scc_cnt]++;
if (x==u) break;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
connect(a,b);
}
for (int i=1;i<=n;i++)
if (!dfn[i]) dfs(i);
for (int u=1;u<=n;u++)
for (int p=last[u];p;p=pre[p])
{
int v=other[p];
if (scc[u]!=scc[v]) out0[scc[u]]=in0[scc[v]]=1;
}
for (int i=1;i<=scc_cnt;i++)
if (out0[i]==0) ans+=siz[i];
printf("%d\n",ans);
return 0;
}