Luogu P2341 [HAOI2006]受欢迎的牛 SCC缩点
把强连通分量缩点,如果有且仅有一个出度为0的强连通分量,那么答案就是他的size;如果有多个入度为0的,那么没有明星牛。
#include<cstdio> #include<iostream> #define R register int using namespace std; inline int g() { R ret=0; register char ch; while(!isdigit(ch=getchar())); do ret=ret*10+(ch^48); while(isdigit(ch=getchar())); return ret; } int n,m,cc,cnt,num,top,ans; int vr[50010],nxt[50010],fir[10010],dfn[10010],low[10010],stk[10010],c[10010],sz[10010],r[10010]; bool vis[10010]; inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;} void tarjan(int u) { dfn[u]=low[u]=++num; stk[++top]=u,vis[u]=true; for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(!dfn[v]) { tarjan(v); low[u]=min(low[u],low[v]); } else if(vis[v]) low[u]=min(low[u],dfn[v]); } if(dfn[u]==low[u]) { R tmp; ++cc; do tmp=stk[top],vis[tmp]=false,c[tmp]=cc,++sz[cc],--top; while(tmp!=u); } } inline void solve() { R tot=0; for(R u=1;u<=n;++u) for(R i=fir[u];i;i=nxt[i]) { R v=vr[i]; if(c[u]!=c[v]) ++r[c[u]];} for(R i=1;i<=cc;++i) if(!r[i]&&++tot>1) {ans=0; break; } else if(!r[i]) ans=sz[i]; printf("%d\n",ans); } signed main() { n=g(),m=g(); for(R i=1,u,v;i<=m;++i) u=g(),v=g(),add(u,v); for(R i=1;i<=n;++i) if(!dfn[i]) tarjan(i); solve(); }
2019.04.18