BZOJ 1051 [HAOI2006]受欢迎的牛

tarjan缩点,之后出度为0的点的size就是答案,若有多个出度为0的点则答案为0;

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<stack>
#include<vector>
typedef long long LL;
const int maxn=50000+299;
using namespace std;
int n,m,u,v,dfs_clock,dfn[maxn],low[maxn],num[maxn],tot;
int fir[maxn],nxt[maxn],to[maxn],ecnt,out[maxn],e[maxn][2],sz[maxn];
void add(int u,int v) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
}
stack<int>sta;
void tarjan(int x) {
    dfn[x]=low[x]=++dfs_clock;
    sta.push(x); 
    for(int i=fir[x];i;i=nxt[i]) {
        if(!dfn[to[i]]) {
            tarjan(to[i]);
            low[x]=min(low[x],low[to[i]]);
        }
        else if(!num[to[i]]) low[x]=min(low[x],dfn[to[i]]);
    }
    if(dfn[x]==low[x]) {
        ++tot;
        for(;;) {
            int u=sta.top();
            sta.pop() ;
            num[u]=tot;
            sz[tot]++;
            if(u==x) break;
        }
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++) {
        scanf("%d%d",&u,&v);
        e[i][0]=u; e[i][1]=v;
        add(u,v);
    }
    for(int i=1;i<=n;i++) 
        if(!dfn[i]) tarjan(i);
    for(int i=1;i<=m;i++) {
        u=num[e[i][0]]; v=num[e[i][1]];
        if(u!=v) out[u]++;
    }
    int flag=0,ans=0;
    for(int i=1;i<=tot;i++) {
        if(!flag&&!out[i]) {
            ans=sz[i];
            flag=1;
        }
        else if(flag&&!out[i]) {
            flag=0;
            break;
        }
    }
    if(!flag) ans=0;
    printf("%d\n",ans);
    return 0;
}
View Code

 

posted @ 2017-09-17 16:29  啊宸  阅读(...)  评论(... 编辑 收藏