BZOJ 1051 [HAOI2006]受欢迎的牛
tarjan缩点,之后出度为0的点的size就是答案,若有多个出度为0的点则答案为0;
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<stack>
#include<vector>
typedef long long LL;
const int maxn=50000+299;
using namespace std;
int n,m,u,v,dfs_clock,dfn[maxn],low[maxn],num[maxn],tot;
int fir[maxn],nxt[maxn],to[maxn],ecnt,out[maxn],e[maxn][2],sz[maxn];
void add(int u,int v) {
nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
}
stack<int>sta;
void tarjan(int x) {
dfn[x]=low[x]=++dfs_clock;
sta.push(x);
for(int i=fir[x];i;i=nxt[i]) {
if(!dfn[to[i]]) {
tarjan(to[i]);
low[x]=min(low[x],low[to[i]]);
}
else if(!num[to[i]]) low[x]=min(low[x],dfn[to[i]]);
}
if(dfn[x]==low[x]) {
++tot;
for(;;) {
int u=sta.top();
sta.pop() ;
num[u]=tot;
sz[tot]++;
if(u==x) break;
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++) {
scanf("%d%d",&u,&v);
e[i][0]=u; e[i][1]=v;
add(u,v);
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i);
for(int i=1;i<=m;i++) {
u=num[e[i][0]]; v=num[e[i][1]];
if(u!=v) out[u]++;
}
int flag=0,ans=0;
for(int i=1;i<=tot;i++) {
if(!flag&&!out[i]) {
ans=sz[i];
flag=1;
}
else if(flag&&!out[i]) {
flag=0;
break;
}
}
if(!flag) ans=0;
printf("%d\n",ans);
return 0;
}