JDOJ-1076: 受欢迎的牛

[文章目录]

Description

在一个有N(1<=N<=10,000)头牛的牛群中,给你M(1<=M<=50,000)个二元组(A,B),表示A认为B是受欢迎的。既然受欢迎是可传递的,那么如果A认为B受欢迎,B又认为C受欢迎,则A也会认为C是受欢迎的,哪怕这不是十分明确的规定。  你的任务是计算被所有其它的牛都喜欢的牛的个数。

tarjan,先缩点,再找;
不过怎么找就是一个问题了,第一遍我是将所有强连通分量直接到达的num[]++;最后看是否有一个强连通分量num[]=n;但是会有一种情况就是,有一个牛和大家都喜欢的牛不是直接相连,这样的话就会使题目解=0。
打完之后感觉巨耗脑细胞,然而只有50分;

实际上该怎么找一个强连通分量呢?应该记录每一个强连通分量的出度;如果有>1个强连通分量出度为0的话,他们两个就一定不能互相到达,无解;如果只有一个的话,显然除了它,每个强连通分量都能到达另一个强连通分量,最后都会汇入到这个强连通分量里。想想看。。。

所以脑细胞都。。。了

#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <iostream>
using namespace std;
int z[11000],top;
int deep[11000],low[11000],belong[11000],sum[11000],tot;
bool inz[11000];
int h[11000],to[51000],nxt[51000],cnt;
int h2[11000],to2[51000],nxt2[51000],tot2,ans;
int a,b,fna,t,n,m,tmp,flag,c;
void add1(int x,int y)
{
    to[++cnt]=y;
    nxt[cnt]=h[x];
    h[x]=cnt;
}
void add2(int x,int y)
{
    to2[++tot2]=y;
    nxt2[tot2]=h2[x];
    h2[x]=tot2;
}
void tarjan(int x)
{
    inz[x]=1;
    z[++top]=x;
    deep[x]=low[x]=++tot;
    for(int i=h[x];i;i=nxt[i])
    {
        if(!deep[to[i]])
        {
            tarjan(to[i]);
            if(low[ to[i] ] <low[x])
                low[x]=low[ to[i] ] ;
        }
        else if(inz[ to[i] ])
        {
            if(deep[ to[i] ]<low[x])
                low[x]=deep[ to[i] ];
        }
    }
    if(deep[x]==low[x])
    {
        ans++;
        do
        {
            t=z[top--];
            inz[t]=0;
            sum[ans]++;
            belong[t]=ans;
            add2(ans,t);
        }while(t!=x);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&a,&b);
        add1(a,b);
    }
    for(int i=1;i<=n;i++)
    {
        if(!deep[i])
            tarjan(i);
    }
    for(int i=1;i<=ans;i++)
    {
        tmp=0;
        for(int j=h2[i];j;j=nxt2[j])
        {
            for(int k=h[ to2[j] ];k;k=nxt[k])
            {
                if(belong[to[k]]!=i)
                {
                    tmp=1;
                }
            }
        }
        if(tmp!=1)
        {
            flag++;
            c=i;
        }
    }
    if(flag==1)
        printf("%d",sum[c]);
    else
        printf("0");
    return 0;
}

 

发表评论

邮箱地址不会被公开。 必填项已用*标注