BZOJ1051 [HAOI2006]受欢迎的牛

题目描述:

每一头牛的愿望就是变成一头最受欢迎的牛。现在有N头牛,给你M对整数(A,B),表示牛A认为牛B受欢迎。 这
种关系是具有传递性的,如果A认为B受欢迎,B认为C受欢迎,那么牛A也认为牛C受欢迎。你的任务是求出有多少头
牛被所有的牛认为是受欢迎的。
 
题解:
tarjan缩点。
由题可得,受欢迎的奶牛只有可能是图中唯一的出度为零的强连通分量中的所有奶牛,
所以若出现两个以上出度为0的强连通分量则不存在明星奶牛,因为那几个出度为零的分量的爱慕无法传递出去。
那唯一的分量能受到其他分量的爱慕同时在分量内相互传递,所以该分量中的所有奶牛都是明星。
附上代码:
#include<cstdio> 
#include<cstring>  
int idx,ans2,low[50001],deep[50001],idx2,cnt,last[50001],x[50001],y[50001],z[50001],top,f[50001],ans[50001],num[50001],n,m;  
bool inz[50001]; 
struct edge
{
    int to,next;
}e[50001];  
int min(int a,int b)  
{  
    if(a<b)
        return a;  
    return b;
}  
void addage(int x,int y)  
{  
     e[++idx].to=y; 
     e[idx].next=last[x]; 
     last[x]=idx;  
}   
void tarjan(int x)  
{  
    low[x]=deep[x]=++cnt;  
    z[++top]=x;   
    inz[x]=1;   
    for(int i=last[x];i>=0;i=e[i].next) 
    {  
        if(!deep[e[i].to])  
         {  
            tarjan(e[i].to);  
            low[x]=min(low[x],low[e[i].to]);  
          }  
        else if(inz[e[i].to]&&low[x]>deep[e[i].to]) 
              low[x]=deep[e[i].to];   
    }   
    if(low[x]==deep[x])  
     {  
        idx2++;
        int t=-1;  
        while(x!=t)
        {  
            t=z[top--];  
            ans[idx2]++;  
            f[t]=idx2;  
            inz[t]=0;  
        } 
     }    
}   
int main()  
{   
    scanf("%d%d",&n,&m); 
    memset(last,-1,sizeof(last)); 
    for(int i=1;i<=m;i++)  
    {  
        scanf("%d%d",&x[i],&y[i]);  
        addage(x[i],y[i]);  
    }
    for(int i=1;i<=n;i++)  
         if(!deep[i]) 
             tarjan(i);    
    for(int i=1;i<=m;i++)  
         if(f[x[i]]!=f[y[i]])  
               num[f[x[i]]]++;   
    for(int i=1;i<=idx2;i++)  
      if(!num[i])  
       {  
            if(ans2)  
            {
                printf("0"); 
                return 0;
            }  
            ans2=i;  
       }  
    printf("%d",ans[ans2]);   
}

 

posted @ 2018-10-19 15:23  jiangminghong  阅读(140)  评论(0编辑  收藏  举报