题目描述:
有n只牛,牛之间存在一些关系,比如a认为b很受欢迎,b认为c很受欢迎,这样呢,a也会认为c很受欢迎,问根据给出的关系,有多少头牛被其他所有的牛都认为是受欢迎的?
解题思路:
对于一个有向无环图来说,其中有且仅有一个点出度为零,那么这个特殊的点,可以由其他任何点到达。那么接下来我们直接对所给的图进行强连通分量划分,然后把每个强连通分量看做一个点,判定出度为零的点有几个,如果有一个就输出这个点对应的强连通分量含有的节点个数,否则为零。
#include <cstring>
#include <cstdio>
#include <string>
#include <algorithm>
using namespace std;
const int maxn=1e4+10;
struct node{
int to,nxt;
}edge[maxn*5];
int head[maxn],tot;
int low[maxn],dfn[maxn],sta[maxn],belg[maxn],out[maxn];
int index,top;
int scc;
bool instack[maxn];
void addedge(int u,int v){
edge[tot].to=v;
edge[tot].nxt=head[u];
head[u]=tot++;
}
void Tarjan(int u){
int v;
low[u]=dfn[u]=++index;
sta[top++]=u;
instack[u]=1;
for(int i=head[u];i!=-1;i=edge[i].nxt){
v=edge[i].to;
if(!dfn[v]){
Tarjan(v);
}
if(instack[v]){
low[u]=min(low[u],low[v]);
}
}
if(low[u]==dfn[u]){
scc++;
do{
v=sta[--top];
instack[v]=0;
belg[v]=scc;
}while(v!=u);
}
}
void init(){
tot=index=scc=top=0;
memset(dfn,0,sizeof dfn);
memset(instack,0,sizeof instack);
memset(low,0,sizeof low);
memset(head,-1,sizeof head);
memset(out,0,sizeof out);
}
int main(){
int n,m;
while(scanf("%d%d",&n,&m)!=EOF){
init();
while(m--){
int u,v;
scanf("%d%d",&u,&v);
addedge(u,v);
}
for(int i=1;i<=n;i++){
if(!dfn[i]){
Tarjan(i);
}
}
int sum=0,x;
for(int i=1;i<=n;i++){
for(int j=head[i];~j;j=edge[j].nxt){
if(belg[i]!=belg[edge[j].to]){
out[belg[i]]++;
}
}
}
for(int i=1;i<=scc;i++){
if(!out[i]){
sum++;
x=i;
}
}
if(sum==1){
sum=0;
for(int i=1;i<=n;i++){
if(belg[i]==x){
sum++;
}
}
printf("%d\n",sum);
}else printf("0\n");
}
}