【luogu2341】 [HAOI2006]受欢迎的牛 [tarjan 缩点]
背一下刚刚出炉的模板 (快乐打水题)
emmmm 反向建边方便后面计算强连通分量的出度(反向建边就把出度变为入度)
缩完点后枚举边 然后就来统计现在的入度
最后就看有没有多于两个0入度的点 如果有 就没有牛可以成为明星
#include<iostream> #include<cstdio> #include<queue> #include<cstring> #include<cmath> #include<vector> #include<stack> #include<algorithm> using namespace std; const int N=10000+5,M=50000+5; int n,m,dfn[N],low[N],inst[N],bl[N],idx=0,Bcnt=0; int sum[N],r[N]; stack<int>s; vector<int>g[N]; template <class t>void rd(t &x){ x=0;int w=0;char ch=0; while(!isdigit(ch)) w|=ch=='-',ch=getchar(); while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); x=w?-x:x; } int head[N],tot=0; struct edge{int u,v,nxt;}e[M]; void add(int u,int v){ e[++tot]=(edge){u,v,head[u]};head[u]=tot; } void tarjan(int u){ dfn[u]=low[u]=++idx; inst[u]=1,s.push(u); for(int i=head[u],v;i;i=e[i].nxt){ v=e[i].v; if(!dfn[v]) tarjan(v),low[u]=min(low[u],low[v]); else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v]; } if(dfn[u]==low[u]){ ++Bcnt; int v; do{ v=s.top();s.pop(); bl[v]=Bcnt; ++sum[Bcnt]; inst[v]=0; }while(u!=v); } } int main(){ freopen("in.txt","r",stdin); rd(n),rd(m); for(int i=1,u,v;i<=m;++i){ rd(u),rd(v); add(v,u); } memset(dfn,0,sizeof(dfn)); for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i); for(int i=1;i<=tot;++i) if(bl[e[i].u]!=bl[e[i].v]) ++r[bl[e[i].v]]; int ans,cnt=0; for(int i=Bcnt;i;--i) if(!r[i]) ans=sum[i],++cnt; if(cnt==1) printf("%d",ans); else printf("0"); return 0; }