题目:在zyh的高中,学生会每一年都会评选受欢迎学生,所谓受欢迎的学生,就是被所有学生喜欢的学生。 每个学生都喜欢自己,碰巧的是,如果学生A 喜欢学生B ,学生B喜欢学生C, 那么学生A也喜欢学生C。 但是学生A喜欢学生B 并不意味着学生B喜欢学生A。 zyh参与了评选工作,苦逼的他被安排去购买奖品,于是他拿到了一张表,这张表有m条记录,每条记录由两个数字a,b组成,表示a,喜欢b ,但是由于学生太多了,他无法知道会有多少个受欢迎的学生,从而无法去购买奖品,你能帮他解决吗?
水题,AC代码:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <stack>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;
int x,y,n,m,head[maxn],tot,cnt,num,low[maxn],dfn[maxn],vis[maxn],belong[maxn],out[maxn];
struct node{
int v,nxt;
}e[maxn];
void init(){
memset(head,-1,sizeof(head));
memset(low,0,sizeof(low));
memset(dfn,0,sizeof(dfn));
memset(vis,0,sizeof(vis));
memset(out,0,sizeof(out));
memset(belong,0,sizeof(belong));
tot=1;
cnt=0;
num=0;
}
void add(int u,int v){
e[tot].v=v;
e[tot].nxt=head[u];
head[u]=tot++;
}
stack<int>s;
void tarjan(int u){
low[u]=dfn[u]=++cnt;
s.push(u);
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(!dfn[v]){
tarjan(v);
low[u]=min(low[v],low[u]);
}
else if(vis[v])low[u]=min(dfn[v],low[u]);
}
if(dfn[u]==low[u]){
num++;
int v;
do{
v=s.top();
s.pop();
vis[v]=0;
belong[v]=num;
}while(u!=v);
}
}
void dfs(int u){
vis[u]=1;
for(int i=head[u];i!=-1;i=e[i].nxt){
int v=e[i].v;
if(belong[u]!=belong[v]){
out[belong[u]]++;
}
if(!vis[v])dfs(v);
}
}
int main(){
init();
cin>>n>>m;
while(m--){
//int x,y;
cin>>x>>y;
add(x,y);
}
for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++)if(!vis[i])dfs(i);
int res=0;
for(int i=1;i<=num;i++){
if(out[i]==0){
if(res==0)res=i;
else{
res=0;//如果缩点以后还有两个答案,那么说明原图不连通,那肯定无法呗被所有奶牛仰慕啊
break;
}
}
}
if(!res)cout<<0;
else{
int ans=0;
for(int i=1;i<=n;i++)if(belong[i]==res)ans++;
cout<<ans;
}
}