HAOI2006 受欢迎的牛 缩点
不难分析出我们就是要求是否有唯一一个出度为0的强连通分量。
Code:
#include<cstdio> #include<stack> #include<algorithm> using namespace std; const int N=50000+3; stack<int>S; int head[N],to[N<<1],nex[N<<1], cnt; int pre[N],low[N],vis[N], sig, scc; int idx[N],siz[N]; int du[N]; void add_edge(int u,int v) { nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v; } void tarjan(int u) { S.push(u); pre[u]=low[u]=++scc; vis[u]=1; for(int v=head[u];v;v=nex[v]) { if(!vis[to[v]]){ tarjan(to[v]);low[u]=min(low[u],low[to[v]]); } else if(vis[to[v]]==1)low[u]=min(low[u],pre[to[v]]); } if(pre[u]==low[u]) { ++sig; for(;;) { int a=S.top();S.pop(); vis[a]=-1,idx[a]=sig,siz[sig]+=1; if(a==u)break; } } } int main() { //freopen("in.txt","r",stdin); int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { int a,b; scanf("%d%d",&a,&b); add_edge(a,b); } for(int i=1;i<=n;++i) if(!vis[i])tarjan(i); int cc=0,ans=0; for(int i=1;i<=n;++i) for(int v=head[i];v;v=nex[v]) if(idx[i]!=idx[to[v]])du[idx[i]]=1; for(int i=1;i<=sig;++i) if(!du[i])cc+=1,ans=siz[i]; if(cc>1)printf("0"); else printf("%d",ans); return 0; }