【强连通分量】Bzoj1051 HAOI2006 受欢迎的牛

Description

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头牛被所有的牛认为是受欢迎的。

 

Solution

那么对于x如果可以也就是所有节点都可以到达x,如果无环也就是x要无出度且无出度的点数正好为1(出边连点必到不了x)。

然而这是有环的,那么把强连通分量缩起来就行了。

 

Code

我这个傻逼现在才会求强连通分量。

而且还只会Kosaraju,现在还没写过Trajan。

#include<cstdio>
const int maxn=1e5+5;

int q[maxn],block[maxn],clock,cnt;
int head[maxn],e[maxn],nxt[maxn],k;
int _head[maxn],_e[maxn],_nxt[maxn];
int adde(int u,int v){
    e[++k]=v;
    nxt[k]=head[u],head[u]=k;
    _e[k]=u;
    _nxt[k]=_head[v],_head[v]=k;
}
int n,m;
int vis[maxn],r[maxn],s[maxn];

int dfs1(int u){
    vis[u]=1;
    for(int i=head[u];i;i=nxt[i]){
        int v=e[i];
        if(!vis[v]) dfs1(v);
    }
    q[++clock]=u;
}

int dfs2(int u){
    block[u]=cnt;
    s[cnt]++;
    for(int i=_head[u];i;i=_nxt[i]){
        int v=_e[i];
        if(!block[v]) dfs2(v);
    }
}

int main(){
    scanf("%d%d",&n,&m);
    int u,v;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        adde(u,v);
    }
    
    for(int i=1;i<=n;i++)
        if(!vis[i]) dfs1(i);
        
    for(int i=n;i>=1;i--)
        if(!block[q[i]]){
            ++cnt;
            dfs2(q[i]);
        }
        
    for(int i=1;i<=k;i++){
        int x=block[_e[i]],y=block[e[i]];
        if(x==y) continue;
        r[x]++;
    }
    
    int ans=0,ansx;
    for(int i=1;i<=cnt;i++)
        if(!r[i]) ans++,ansx=i;
    if(ans==1) printf("%d\n",s[ansx]);
    else printf("0\n");
    return 0;
}

 

 

 
posted @ 2015-06-03 01:33  CyanNode  阅读(193)  评论(0编辑  收藏  举报