bzoj1051: [HAOI2006]受欢迎的牛

tarjan缩点。网上的代码都没有缩点是把vis变成另外一个值,我也不知道是为什么。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 200000 + 10;
const int maxm = 1000000 + 10;

int g[maxn],v[maxm],next[maxm],eid;
int n,m,cid=0,vid=0,sp=0,res;
int dfn[maxn],low[maxn],vis[maxn];
int s[maxn],size[maxn],color[maxn],out[maxn];

void addedge(int a,int b) {
    v[eid]=b; next[eid]=g[a]; g[a]=eid++;
}

void build() {
    memset(g,-1,sizeof(g));
    scanf("%d%d",&n,&m);
    for(int i=1,a,b;i<=m;i++) {
        scanf("%d%d",&a,&b);
        addedge(a,b);
    }
}

void tarjan(int u) {
    vis[u]=1; s[++sp]=u; dfn[u]=low[u]=++vid;
    for(int i=g[u];~i;i=next[i]) {
        if(vis[v[i]]==0) {
            tarjan(v[i]);
            low[u]=min(low[u],low[v[i]]);
        }
        else if(vis[v[i]]==1) low[u]=min(low[u],dfn[v[i]]);    
    }
    if(dfn[u]==low[u]) {
        ++cid;
        do {
            color[s[sp]]=cid;
            size[cid]++;
            vis[s[sp]]=2;
        } while(s[sp--]!=u);
    }        
}

void solve() {
    for(int i=1;i<=n;i++) if(!vis[i]) tarjan(i);
    res=-1;
    for(int u=1;u<=n;u++)
    for(int i=g[u];~i;i=next[i]) if(color[u]!=color[v[i]]) out[color[u]]++;
    for(int i=1;i<=cid;i++) if(out[i]==0) {
        if(res==-1) res=size[i];
        else {
            res=0;
            break;
        }
    }
    printf("%d
",res);
}


int main() {
    build();
    solve();
    return 0;
}
原文地址:https://www.cnblogs.com/invoid/p/5511072.html