bzoj 1051

先Tarjan缩点。

然后枚举每一条边,统计每一个强连通分量出度是否为0。

如果只有一个强连通分量的出度为0那么答案就是这个强连通分量中牛的个数。

否则答案就是0。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxn=10001,maxe=50001;
int read(){
    char c; while(!isdigit(c=getchar())); int x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x;
}
int cnt,hed[maxn],nex[maxe],lnk[maxe];
void add(int u,int v){
    nex[++cnt]=hed[u];
    lnk[hed[u]=cnt]=v;
}
int num,top,tme,sta[maxn],dfn[maxn],low[maxn],vis[maxn],tot[maxn];
void tarjan(int o){
    sta[++top]=o;
    vis[o]=low[o]=++tme;
    for(int i=hed[o];i;i=nex[i])
        if(!dfn[lnk[i]]){
            if(!vis[lnk[i]]) tarjan(lnk[i]);
            low[o]=min(low[lnk[i]],low[o]);
        }
    if(low[o]==vis[o]){
        ++num;
        while(dfn[sta[top]]=num,tot[num]++,sta[top--]!=o);
    }
}
int yes[maxn];
int main(){
    int n=read(),m=read(),val=0,ans=0;
    while(m--){
        int u=read(),v=read();
        add(u,v);
    }
    for(int i=1;i<=n;i+=1) if(!dfn[i]) tarjan(i);
    for(int i=1;i<=n;i+=1)
        for(int j=hed[i];j;j=nex[j])
            if(dfn[i]!=dfn[lnk[j]]){yes[dfn[i]]=1; break;}
    for(int i=1;i<=num;i+=1) val+=yes[i];
    if(val==num-1)
        for(int i=1;i<=num;i+=1) if(!yes[i]) ans=tot[i];
    printf("%d",ans);
    return 0;
}

 

posted @ 2017-10-22 20:47  或是七一  阅读(93)  评论(0编辑  收藏  举报