受欢迎的牛

https://loj.ac/problem/10091

题目描述

  有N头牛,M对关系(A,B),表示A认为B是受欢迎的,关系可传递,求多少头牛被出自己以外所有的牛认为是受欢迎的。

思路

  由于喜欢的关系可以传递,所以这M对关系就形成了一张有向图,而要求的就是对于每一头牛它是否直接或间接被其他牛认为受欢迎,我们考虑对于一个强连通分量,在这个强连通分量中的牛一定互相认为受欢迎,我们可以直接把它看做“一头牛”。所以在进行缩点之后,必定是一张DAG,而对于这张图,我们考虑如果它符合条件,那么它的出度必定为0,否则就会形成环。并且如果出度为0的强连通分量不止一个,显然也无法达到。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e4+10,M=5e5+10;

int nxt[M],head[N],to[M],tot;
void add_edge(int x,int y)
{
    nxt[++tot]=head[x];
    head[x]=tot;
    to[tot]=y;
}

int dfn[N],low[N],st[N],idx,co[N],col,top,siz[N];
void tarjan(int u)
{
    dfn[u]=low[u]=++idx;
    st[++top]=u;
    for(int i=head[u];i;i=nxt[i])
    {
        int v=to[i];
        if(!dfn[v])
        {
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else if(!co[v])
            low[u]=min(low[u],dfn[v]);
    }
    if(low[u]==dfn[u])
    {
        co[u]=++col;
        ++siz[col];
        while(st[top]!=u)
        {
            ++siz[col];
            co[st[top]]=col;
            --top;
        }
        --top;
    }
}
int out[N];
int main() 
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;++i)
    {
        int x,y;
        scanf("%d%d",&x,&y);
        add_edge(x,y);    
    }    
    for(int i=1;i<=n;++i)
        if(!dfn[i])tarjan(i);
    int ans=0,sum=0;
    for(int i=1;i<=n;++i)
        for(int j=head[i];j;j=nxt[j])
            if(co[i]!=co[to[j]])++out[co[i]];
    for(int i=1;i<=col;++i)
        if(!out[i])ans=siz[i],++sum;
    if(sum==1)printf("%d",ans);
    else printf("0");
    return 0;
}

 

posted @ 2019-10-23 18:55  fbz  阅读(130)  评论(0编辑  收藏  举报