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

猜你喜欢

转载自www.cnblogs.com/Jackpei/p/10732554.html